提交 a44ca008 编写于 作者: S Sandeep Somavarapu

#1927 Global action to toggle multi line messages

上级 ad0bf305
......@@ -6,7 +6,7 @@
import * as paths from 'vs/base/common/paths';
import { URI } from 'vs/base/common/uri';
import { Range, IRange } from 'vs/editor/common/core/range';
import { IMarker, MarkerSeverity, IRelatedInformation } from 'vs/platform/markers/common/markers';
import { IMarker, MarkerSeverity, IRelatedInformation, IMarkerData } from 'vs/platform/markers/common/markers';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { values } from 'vs/base/common/map';
import { memoize } from 'vs/base/common/decorators';
......@@ -64,15 +64,17 @@ export class Marker {
get resource(): URI { return this.marker.resource; }
get range(): IRange { return this.marker; }
private _lines: string[];
get lines(): string[] {
if (!this._lines) {
this._lines = this.marker.message.split(/\r\n|\r|\n/g);
}
return this._lines;
}
@memoize
get hash(): string {
const hasher = new Hasher();
hasher.hash(this.resource.toString());
hasher.hash(this.marker.startLineNumber);
hasher.hash(this.marker.startColumn);
hasher.hash(this.marker.endLineNumber);
hasher.hash(this.marker.endColumn);
return `${hasher.value}`;
return IMarkerData.makeKey(this.marker);
}
constructor(
......@@ -80,14 +82,6 @@ export class Marker {
readonly relatedInformation: RelatedInformation[] = []
) { }
private _lines: string[];
get lines(): string[] {
if (!this._lines) {
this._lines = this.marker.message.split(/\r\n|\r|\n/g);
}
return this._lines;
}
toString(): string {
return JSON.stringify({
...this.marker,
......
......@@ -14,7 +14,7 @@ import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/
import Constants from 'vs/workbench/parts/markers/electron-browser/constants';
import { Marker, ResourceMarkers, RelatedInformation, MarkersModel } from 'vs/workbench/parts/markers/electron-browser/markersModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { MarkersFilterActionItem, MarkersFilterAction, QuickFixAction, QuickFixActionItem, IMarkersFilterActionChangeEvent, IMarkerFilterController } from 'vs/workbench/parts/markers/electron-browser/markersPanelActions';
import { MarkersFilterActionItem, MarkersFilterAction, QuickFixAction, QuickFixActionItem, IMarkersFilterActionChangeEvent, IMarkerFilterController, ToggleLineModeAction } from 'vs/workbench/parts/markers/electron-browser/markersPanelActions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import Messages from 'vs/workbench/parts/markers/electron-browser/messages';
import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations';
......@@ -41,6 +41,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { domEvent } from 'vs/base/browser/event';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
function createModelIterator(model: MarkersModel): Iterator<ITreeElement<TreeElement>> {
const resourcesIt = Iterator.fromArray(model.resourceMarkers);
......@@ -85,6 +86,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
private cachedFilterStats: { total: number; filtered: number; } | undefined = undefined;
private currentResourceGotAddedToMarkersData: boolean = false;
private markersViewState: MarkersViewState;
private disposables: IDisposable[] = [];
constructor(
@IInstantiationService private instantiationService: IInstantiationService,
......@@ -103,6 +106,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
super(Constants.MARKERS_PANEL_ID, telemetryService, themeService, storageService);
this.panelFoucusContextKey = Constants.MarkerPanelFocusContextKey.bindTo(contextKeyService);
this.panelState = this.getMemento(StorageScope.WORKSPACE);
this.markersViewState = new MarkersViewState();
this.markersViewState.onDidChangeViewState(this.refreshPanel, this, this.disposables);
this.setCurrentActiveEditor();
}
......@@ -278,11 +283,11 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
const onDidChangeRenderNodeCount = new Relay<ITreeNode<any, any>>();
const virtualDelegate = new VirtualDelegate();
const virtualDelegate = new VirtualDelegate(this.markersViewState);
const renderers = [
this.instantiationService.createInstance(FileResourceMarkersRenderer, onDidChangeRenderNodeCount.event),
this.instantiationService.createInstance(ResourceMarkersRenderer, onDidChangeRenderNodeCount.event),
this.instantiationService.createInstance(MarkerRenderer, a => this.getActionItem(a)),
this.instantiationService.createInstance(MarkerRenderer, this.markersViewState, a => this.getActionItem(a)),
this.instantiationService.createInstance(RelatedInformationRenderer)
];
this.filter = new Filter();
......@@ -350,7 +355,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
});
this.filterAction = this.instantiationService.createInstance(MarkersFilterAction, { filterText: this.panelState['filter'] || '', filterHistory: this.panelState['filterHistory'] || [], useFilesExclude: !!this.panelState['useFilesExclude'] });
this.actions = [this.filterAction, this.collapseAllAction];
this.actions = [this.filterAction, this.instantiationService.createInstance(ToggleLineModeAction, this.markersViewState), this.collapseAllAction];
}
private createListeners(): void {
......@@ -656,5 +661,25 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
public dispose(): void {
super.dispose();
this.tree.dispose();
this.markersViewState.dispose();
this.disposables = dispose(this.disposables);
}
}
export class MarkersViewState extends Disposable {
private readonly _onDidChangeViewState: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChangeViewState: Event<void> = this._onDidChangeViewState.event;
private _multiline: boolean = true;
get multiline(): boolean {
return this._multiline;
}
set multiline(value: boolean) {
if (this._multiline !== value) {
this._multiline = value;
this._onDidChangeViewState.fire();
}
}
}
\ No newline at end of file
......@@ -32,6 +32,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
import { Event } from 'vs/base/common/event';
import { FilterOptions } from 'vs/workbench/parts/markers/electron-browser/markersFilterOptions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { MarkersViewState } from 'vs/workbench/parts/markers/electron-browser/markersPanel';
export class ToggleMarkersPanelAction extends TogglePanelAction {
......@@ -289,6 +290,34 @@ export class MarkersFilterActionItem extends BaseActionItem {
}
}
export class ToggleLineModeAction extends Action {
public static readonly ID: string = 'workbench.actions.problems.toggleLineMode';
private disposables: IDisposable[] = [];
constructor(private readonly viewState: MarkersViewState) {
super(ToggleLineModeAction.ID);
this.update();
viewState.onDidChangeViewState(this.update, this, this.disposables);
}
private update(): void {
this.tooltip = this.viewState.multiline ? localize('singleline', "Show message in single line") : localize('multiline', "Show message in multiple lines");
this.class = this.viewState.multiline ? 'octicon octicon-fold' : 'octicon octicon-unfold';
}
run(): Promise<void> {
this.viewState.multiline = !this.viewState.multiline;
return Promise.resolve();
}
dispose(): void {
dispose(this.disposables);
}
}
export class QuickFixAction extends Action {
public static readonly ID: string = 'workbench.actions.problems.quickfix';
......
......@@ -27,6 +27,7 @@ import { IMatch } from 'vs/base/common/filters';
import { Event } from 'vs/base/common/event';
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { MarkersViewState } from 'vs/workbench/parts/markers/electron-browser/markersPanel';
export type TreeElement = ResourceMarkers | Marker | RelatedInformation;
......@@ -74,8 +75,10 @@ const enum TemplateId {
export class VirtualDelegate implements IListVirtualDelegate<TreeElement> {
constructor(private readonly markersViewState: MarkersViewState) { }
getHeight(element: TreeElement): number {
if (element instanceof Marker) {
if (element instanceof Marker && this.markersViewState.multiline) {
return element.lines.length * 22;
}
return 22;
......@@ -209,6 +212,7 @@ export class FileResourceMarkersRenderer extends ResourceMarkersRenderer {
export class MarkerRenderer implements ITreeRenderer<Marker, MarkerFilterData, IMarkerTemplateData> {
constructor(
private readonly markersViewState: MarkersViewState,
private actionItemProvider: IActionItemProvider,
@IInstantiationService protected instantiationService: IInstantiationService
) { }
......@@ -217,7 +221,7 @@ export class MarkerRenderer implements ITreeRenderer<Marker, MarkerFilterData, I
renderTemplate(container: HTMLElement): IMarkerTemplateData {
const data: IMarkerTemplateData = Object.create(null);
data.markerWidget = new MarkerWidget(container, this.actionItemProvider, this.instantiationService);
data.markerWidget = new MarkerWidget(container, this.markersViewState, this.actionItemProvider, this.instantiationService);
return data;
}
......@@ -235,18 +239,19 @@ class MarkerWidget extends Disposable {
private readonly actionBar: ActionBar;
private readonly icon: HTMLElement;
private readonly messageContainer: HTMLElement;
private readonly messageAndDetailsContainer: HTMLElement;
private disposables: IDisposable[] = [];
constructor(
parent: HTMLElement, actionItemProvider: IActionItemProvider,
parent: HTMLElement,
private readonly markersViewState: MarkersViewState,
actionItemProvider: IActionItemProvider,
private instantiationService: IInstantiationService
) {
super();
const actionsContainer = dom.append(parent, dom.$('.actions'));
this.actionBar = this._register(new ActionBar(actionsContainer, { actionItemProvider }));
this.actionBar = this._register(new ActionBar(dom.append(parent, dom.$('.actions')), { actionItemProvider }));
this.icon = dom.append(parent, dom.$('.icon'));
this.messageContainer = dom.append(parent, dom.$('.marker-message'));
this.messageAndDetailsContainer = dom.append(parent, dom.$('.marker-message-details'));
this._register(toDisposable(() => this.disposables = dispose(this.disposables)));
}
......@@ -255,9 +260,9 @@ class MarkerWidget extends Disposable {
if (this.disposables.length) {
this.disposables = dispose(this.disposables);
}
dom.clearNode(this.messageContainer);
dom.clearNode(this.messageAndDetailsContainer);
this.icon.className = 'icon ' + MarkerWidget.iconClassNameFor(marker);
this.icon.className = 'marker-icon ' + MarkerWidget.iconClassNameFor(marker);
this.actionBar.clear();
const quickFixAction = this.instantiationService.createInstance(QuickFixAction, element);
......@@ -270,15 +275,17 @@ class MarkerWidget extends Disposable {
}, this, this.disposables);
const lineMatches = filterData && filterData.lineMatches || [];
let lastLineElement = this.messageContainer;
const messageContainer = dom.append(this.messageAndDetailsContainer, dom.$('.marker-message'));
dom.toggleClass(messageContainer, 'multiline', this.markersViewState.multiline);
let lastLineElement = messageContainer;
for (let index = 0; index < lines.length; index++) {
lastLineElement = dom.append(this.messageContainer, dom.$('.marker-message-line'));
lastLineElement = dom.append(messageContainer, dom.$('.marker-message-line'));
const highlightedLabel = new HighlightedLabel(lastLineElement, false);
highlightedLabel.set(lines[index], lineMatches[index]);
this.disposables.push(highlightedLabel);
}
this.renderDetails(marker, filterData, lastLineElement);
this.renderDetails(marker, filterData, this.markersViewState.multiline ? lastLineElement : this.messageAndDetailsContainer);
}
private onDidQuickFixesActionEnable(enabled: boolean): void {
......
......@@ -109,13 +109,22 @@
margin-left: 10px;
}
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message {
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message-details,
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message:not(.multiline) {
display: flex;
flex-direction: column;
overflow: hidden;
}
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message.multiline {
white-space: pre;
flex: 1;
}
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message:not(.multiline) .marker-message-line {
overflow: hidden;
text-overflow: ellipsis;
}
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message .details-container {
display: flex;
}
......@@ -146,32 +155,32 @@
font-weight: bold;
}
.markers-panel .monaco-tl-contents > .icon {
.markers-panel .monaco-tl-contents .marker-icon {
height: 22px;
flex: 0 0 16px;
}
.markers-panel .icon.warning {
.markers-panel .marker-icon.warning {
background: url('status-warning.svg') center center no-repeat;
}
.markers-panel .icon.error {
.markers-panel .marker-icon.error {
background: url('status-error.svg') center center no-repeat;
}
.markers-panel .icon.info {
.markers-panel .marker-icon.info {
background: url('status-info.svg') center center no-repeat;
}
.vs-dark .markers-panel .icon.warning {
.vs-dark .markers-panel .marker-icon.warning {
background: url('status-warning-inverse.svg') center center no-repeat;
}
.vs-dark .markers-panel .icon.error {
.vs-dark .markers-panel .marker-icon.error {
background: url('status-error-inverse.svg') center center no-repeat;
}
.vs-dark .markers-panel .icon.info {
.vs-dark .markers-panel .marker-icon.info {
background: url('status-info-inverse.svg') center center no-repeat;
}
......@@ -188,9 +197,9 @@
display: none;
}
.markers-panel .monaco-list-row:hover .monaco-tl-contents > .icon.quickFix,
.markers-panel .monaco-list-row.selected .monaco-tl-contents > .icon.quickFix,
.markers-panel .monaco-list-row.focused .monaco-tl-contents > .icon.quickFix {
.markers-panel .monaco-list-row:hover .monaco-tl-contents > .marker-icon.quickFix,
.markers-panel .monaco-list-row.selected .monaco-tl-contents > .marker-icon.quickFix,
.markers-panel .monaco-list-row.focused .monaco-tl-contents > .marker-icon.quickFix {
display: none;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册