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

#1927

- Add toggle action per problem
- Remove global toggle action
- Add commands to show multi or single line
上级 35cd14ec
......@@ -12,6 +12,8 @@ export default {
RELATED_INFORMATION_COPY_MESSAGE_ACTION_ID: 'problems.action.copyRelatedInformationMessage',
FOCUS_PROBLEMS_FROM_FILTER: 'problems.action.focusProblemsFromFilter',
MARKERS_PANEL_FOCUS_FILTER: 'problems.action.focusFilter',
MARKERS_PANEL_SHOW_MULTILINE_MESSAGE: 'problems.action.showMultilineMessage',
MARKERS_PANEL_SHOW_SINGLELINE_MESSAGE: 'problems.action.showSinglelineMessage',
MARKER_OPEN_SIDE_ACTION_ID: 'problems.action.openToSide',
MARKER_SHOW_PANEL_ID: 'workbench.action.showErrorsWarnings',
......
......@@ -5,7 +5,7 @@
import { clipboard } from 'electron';
import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
......@@ -155,7 +155,38 @@ registerAction({
},
}
});
registerAction({
id: Constants.MARKERS_PANEL_SHOW_MULTILINE_MESSAGE,
handler(accessor) {
const panelService = accessor.get(IPanelService);
const panel = panelService.getActivePanel();
if (panel instanceof MarkersPanel) {
panel.markersViewState.multiline = true;
}
},
title: localize('show multiline', "Show message in multiple lines"),
category: localize('problems', "Problems"),
menu: {
menuId: MenuId.CommandPalette,
when: new RawContextKey<string>('activePanel', Constants.MARKERS_PANEL_ID)
}
});
registerAction({
id: Constants.MARKERS_PANEL_SHOW_SINGLELINE_MESSAGE,
handler(accessor) {
const panelService = accessor.get(IPanelService);
const panel = panelService.getActivePanel();
if (panel instanceof MarkersPanel) {
panel.markersViewState.multiline = false;
}
},
title: localize('show singleline', "Show message in single line"),
category: localize('problems', "Problems"),
menu: {
menuId: MenuId.CommandPalette,
when: new RawContextKey<string>('activePanel', Constants.MARKERS_PANEL_ID)
}
});
function copyMarker(panelService: IPanelService) {
const activePanel = panelService.getActivePanel();
......
......@@ -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, ToggleLineModeAction } from 'vs/workbench/parts/markers/electron-browser/markersPanelActions';
import { MarkersFilterActionItem, MarkersFilterAction, QuickFixAction, QuickFixActionItem, IMarkersFilterActionChangeEvent, IMarkerFilterController } 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';
......@@ -86,7 +86,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
private cachedFilterStats: { total: number; filtered: number; } | undefined = undefined;
private currentResourceGotAddedToMarkersData: boolean = false;
private markersViewState: MarkersViewState;
readonly markersViewState: MarkersViewState;
private disposables: IDisposable[] = [];
constructor(
......@@ -107,7 +107,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
this.panelFoucusContextKey = Constants.MarkerPanelFocusContextKey.bindTo(contextKeyService);
this.panelState = this.getMemento(StorageScope.WORKSPACE);
this.markersViewState = new MarkersViewState(this.panelState['multiline']);
this.markersViewState.onDidChangeViewState(this.refreshPanel, this, this.disposables);
this.markersViewState.onDidChangeViewState(this.onDidChangeViewState, this, this.disposables);
this.setCurrentActiveEditor();
}
......@@ -217,6 +217,10 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
}
}
private onDidChangeViewState(marker?: Marker): void {
this.refreshPanel();
}
private updateFilter() {
this.cachedFilterStats = undefined;
const excludeExpression = this.getExcludeExpression(this.filterAction.useFilesExclude);
......@@ -355,7 +359,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.instantiationService.createInstance(ToggleLineModeAction, this.markersViewState), this.collapseAllAction];
this.actions = [this.filterAction, this.collapseAllAction];
}
private createListeners(): void {
......@@ -373,6 +377,16 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
}
private onDidChangeModel(resources: URI[]) {
for (const resource of resources) {
const resourceMarkers = this.markersWorkbenchService.markersModel.getResourceMarkers(resource);
if (resourceMarkers) {
for (const marker of resourceMarkers.markers) {
this.markersViewState.add(marker);
}
} else {
this.markersViewState.remove(resource);
}
}
this.currentResourceGotAddedToMarkersData = this.currentResourceGotAddedToMarkersData || this.isCurrentResourceGotAddedToMarkersData(resources);
this.refreshPanel();
this.updateRangeHighlights();
......
......@@ -32,7 +32,6 @@ 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/markersTreeViewer';
export class ToggleMarkersPanelAction extends TogglePanelAction {
......@@ -290,34 +289,6 @@ 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,9 @@ import { IMatch } from 'vs/base/common/filters';
import { Event, Emitter } from 'vs/base/common/event';
import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { Action } from 'vs/base/common/actions';
import { localize } from 'vs/nls';
export type TreeElement = ResourceMarkers | Marker | RelatedInformation;
......@@ -77,8 +80,10 @@ export class VirtualDelegate implements IListVirtualDelegate<TreeElement> {
constructor(private readonly markersViewState: MarkersViewState) { }
getHeight(element: TreeElement): number {
if (element instanceof Marker && this.markersViewState.multiline) {
return element.lines.length * 22;
if (element instanceof Marker) {
const viewState = this.markersViewState.getViewState(element);
const noOfLines = !viewState || viewState.multiline ? element.lines.length : 1;
return noOfLines * 22;
}
return 22;
}
......@@ -238,6 +243,7 @@ class MarkerWidget extends Disposable {
private readonly actionBar: ActionBar;
private readonly icon: HTMLElement;
private readonly multilineActionbar: ActionBar;
private readonly messageAndDetailsContainer: HTMLElement;
private disposables: IDisposable[] = [];
......@@ -250,32 +256,55 @@ class MarkerWidget extends Disposable {
super();
this.actionBar = this._register(new ActionBar(dom.append(parent, dom.$('.actions')), { actionItemProvider }));
this.icon = dom.append(parent, dom.$('.icon'));
this.multilineActionbar = this._register(new ActionBar(dom.append(parent, dom.$('.multiline-actions')), { actionItemProvider }));
this.messageAndDetailsContainer = dom.append(parent, dom.$('.marker-message-details'));
this._register(toDisposable(() => this.disposables = dispose(this.disposables)));
}
render(element: Marker, filterData: MarkerFilterData): void {
const { marker, lines } = element;
this.actionBar.clear();
this.multilineActionbar.clear();
if (this.disposables.length) {
this.disposables = dispose(this.disposables);
}
dom.clearNode(this.messageAndDetailsContainer);
this.icon.className = 'marker-icon ' + MarkerWidget.iconClassNameFor(marker);
this.renderQuickfixActionbar(element);
this.icon.className = 'marker-icon ' + MarkerWidget.iconClassNameFor(element.marker);
this.renderMultilineActionbar(element);
this.actionBar.clear();
const quickFixAction = this.instantiationService.createInstance(QuickFixAction, element);
this.renderMessageAndDetails(element, filterData);
}
private renderQuickfixActionbar(marker: Marker): void {
const quickFixAction = this.instantiationService.createInstance(QuickFixAction, marker);
this.actionBar.push([quickFixAction], { icon: true, label: false });
this.onDidQuickFixesActionEnable(quickFixAction.enabled);
dom.toggleClass(this.icon, 'quickFix', quickFixAction.enabled);
quickFixAction.onDidChange(({ enabled }) => {
if (!isUndefinedOrNull(enabled)) {
this.onDidQuickFixesActionEnable(enabled);
dom.toggleClass(this.icon, 'quickFix', enabled);
}
}, this, this.disposables);
}
private renderMultilineActionbar(marker: Marker): void {
const viewState = this.markersViewState.getViewState(marker);
const multiline = viewState && viewState.multiline;
const action = new Action('problems.action.toggleMultiline');
action.enabled = viewState && marker.lines.length > 1;
action.tooltip = multiline ? localize('single line', "Show message in single line") : localize('multi line', "Show message in multiple lines");
action.class = multiline ? 'octicon octicon-chevron-up' : 'octicon octicon-chevron-down';
action.run = () => { if (viewState) { viewState.multiline = !viewState.multiline; } return Promise.resolve(); };
this.multilineActionbar.push([action], { icon: true, label: false });
}
private renderMessageAndDetails(element: Marker, filterData: MarkerFilterData) {
const { marker, lines } = element;
const viewState = this.markersViewState.getViewState(element);
const multiline = !viewState || viewState.multiline;
const lineMatches = filterData && filterData.lineMatches || [];
const messageContainer = dom.append(this.messageAndDetailsContainer, dom.$('.marker-message'));
dom.toggleClass(messageContainer, 'multiline', this.markersViewState.multiline);
dom.toggleClass(messageContainer, 'multiline', multiline);
let lastLineElement = messageContainer;
for (let index = 0; index < lines.length; index++) {
......@@ -284,11 +313,7 @@ class MarkerWidget extends Disposable {
highlightedLabel.set(lines[index], lineMatches[index]);
this.disposables.push(highlightedLabel);
}
this.renderDetails(marker, filterData, this.markersViewState.multiline ? lastLineElement : this.messageAndDetailsContainer);
}
private onDidQuickFixesActionEnable(enabled: boolean): void {
dom.toggleClass(this.icon, 'quickFix', enabled);
this.renderDetails(marker, filterData, multiline ? lastLineElement : this.messageAndDetailsContainer);
}
private renderDetails(marker: IMarker, filterData: MarkerFilterData, parent: HTMLElement): void {
......@@ -451,25 +476,103 @@ export class Filter implements ITreeFilter<TreeElement, FilterData> {
}
}
export class MarkersViewState extends Disposable {
export class MarkerViewState 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();
}
}
}
export class MarkersViewState extends Disposable {
private readonly _onDidChangeViewState: Emitter<Marker | undefined> = this._register(new Emitter<Marker | undefined>());
readonly onDidChangeViewState: Event<Marker | undefined> = this._onDidChangeViewState.event;
private readonly markersViewStates: Map<string, { viewState: MarkerViewState, disposables: IDisposable[] }> = new Map<string, { viewState: MarkerViewState, disposables: IDisposable[] }>();
private readonly markersPerResource: Map<string, Marker[]> = new Map<string, Marker[]>();
private bulkUpdate: boolean = false;
constructor(multiline: boolean = true) {
super();
this._multiline = multiline;
}
add(marker: Marker): void {
if (!this.markersViewStates.has(marker.hash)) {
const disposables: IDisposable[] = [];
const viewState = new MarkerViewState();
viewState.multiline = this.multiline;
viewState.onDidChangeViewState(() => {
if (!this.bulkUpdate) {
this._onDidChangeViewState.fire(marker);
}
}, this, disposables);
this.markersViewStates.set(marker.hash, { viewState, disposables });
const markers = this.markersPerResource.get(marker.resource.toString()) || [];
markers.push(marker);
this.markersPerResource.set(marker.resource.toString(), markers);
}
}
remove(resource: URI): void {
const markers = this.markersPerResource.get(resource.toString()) || [];
for (const marker of markers) {
const value = this.markersViewStates.get(marker.hash);
if (value) {
dispose(value.disposables);
}
this.markersViewStates.delete(marker.hash);
}
this.markersPerResource.delete(resource.toString());
}
getViewState(marker: Marker): MarkerViewState | null {
const value = this.markersViewStates.get(marker.hash);
return value ? value.viewState : null;
}
private _multiline: boolean = true;
get multiline(): boolean {
return this._multiline;
}
set multiline(value: boolean) {
let changed = false;
if (this._multiline !== value) {
this._multiline = value;
changed = true;
}
this.bulkUpdate = true;
this.markersViewStates.forEach(({ viewState }) => {
if (viewState.multiline !== value) {
viewState.multiline = value;
changed = true;
}
});
this.bulkUpdate = false;
if (changed) {
this._onDidChangeViewState.fire();
}
}
dispose(): void {
this.markersViewStates.forEach(({ disposables }) => dispose(disposables));
this.markersViewStates.clear();
this.markersPerResource.clear();
super.dispose();
}
}
\ No newline at end of file
......@@ -137,12 +137,16 @@
content: ')';
}
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message,
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .details-container .marker-source,
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .details-container .marker-line {
margin-left: 6px;
}
.markers-panel .monaco-tl-contents .marker-icon,
.markers-panel .monaco-tl-contents .actions .action-item {
margin-right: 6px;
}
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-source,
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .related-info-resource,
.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .related-info-resource-separator,
......@@ -209,6 +213,7 @@
display: block;
}
.markers-panel .monaco-tl-contents .multiline-actions .action-label,
.markers-panel .monaco-tl-contents .actions .action-label {
width: 16px;
height: 100%;
......@@ -216,6 +221,11 @@
background-repeat: no-repeat;
}
.markers-panel .monaco-tl-contents .multiline-actions .action-label {
line-height: 22px;
}
.markers-panel .monaco-tl-contents .multiline-actions .action-item.disabled,
.markers-panel .monaco-tl-contents .actions .action-item.disabled {
display: none;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册