diff --git a/src/vs/workbench/parts/markers/browser/markersPanel.ts b/src/vs/workbench/parts/markers/browser/markersPanel.ts index 6767bce8c4fec469911f12c29faa6adbd50cc829..6cd0676b79cc8d1a2b199ee8ceea891ce8adc161 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanel.ts @@ -13,13 +13,12 @@ import dom = require('vs/base/browser/dom'); import builder = require('vs/base/browser/builder'); import { IAction, Action } from 'vs/base/common/actions'; import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IMarkerService } from 'vs/platform/markers/common/markers'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { Panel } from 'vs/workbench/browser/panel'; import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import Constants from 'vs/workbench/parts/markers/common/constants'; -import { MarkersModel, Marker, Resource, FilterOptions } from 'vs/workbench/parts/markers/common/markersModel'; +import { Marker, Resource } from 'vs/workbench/parts/markers/common/markersModel'; import { Controller } from 'vs/workbench/parts/markers/browser/markersTreeController'; import * as Viewer from 'vs/workbench/parts/markers/browser/markersTreeViewer'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -33,13 +32,10 @@ import { debounceEvent } from 'vs/base/common/event'; import { SimpleFileResourceDragAndDrop } from 'vs/base/parts/tree/browser/treeDnd'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { WorkbenchTree } from 'vs/platform/list/browser/listService'; -import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; -import { localize } from 'vs/nls'; +import { IMarkersWorkbenchService } from 'vs/workbench/parts/markers/common/markers'; export class MarkersPanel extends Panel { - public markersModel: MarkersModel; - private delayedRefresh: Delayer; private lastSelectedRelativeTop: number = 0; @@ -61,13 +57,12 @@ export class MarkersPanel extends Panel { constructor( @IInstantiationService private instantiationService: IInstantiationService, - @IMarkerService private markerService: IMarkerService, @IEditorGroupService private editorGroupService: IEditorGroupService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IConfigurationService private configurationService: IConfigurationService, @ITelemetryService telemetryService: ITelemetryService, @IThemeService themeService: IThemeService, - @IActivityService private activityService: IActivityService + @IMarkersWorkbenchService private markersWorkbenchService: IMarkersWorkbenchService ) { super(Constants.MARKERS_PANEL_ID, telemetryService, themeService); this.delayedRefresh = new Delayer(500); @@ -76,7 +71,6 @@ export class MarkersPanel extends Panel { public create(parent: builder.Builder): TPromise { super.create(parent); - this.markersModel = new MarkersModel(); this.rangeHighlightDecorations = this.instantiationService.createInstance(RangeHighlightDecorations); this.toUnbind.push(this.rangeHighlightDecorations); @@ -91,9 +85,7 @@ export class MarkersPanel extends Panel { this.createActions(); this.createListeners(); - this.render(); - - return TPromise.as(null); + return this.render(); } public getTitle(): string { @@ -109,7 +101,7 @@ export class MarkersPanel extends Panel { return; } - if (this.markersModel.hasFilteredResources()) { + if (this.markersWorkbenchService.markersModel.hasFilteredResources()) { this.tree.DOMFocus(); if (this.tree.getSelection().length === 0) { this.tree.focusFirst(); @@ -136,7 +128,7 @@ export class MarkersPanel extends Panel { } public getActions(): IAction[] { - this.collapseAllAction.enabled = this.markersModel.hasFilteredResources(); + this.collapseAllAction.enabled = this.markersWorkbenchService.markersModel.hasFilteredResources(); return this.actions; } @@ -172,12 +164,11 @@ export class MarkersPanel extends Panel { } private refreshPanel(): TPromise { - this.refreshBadge(); if (this.isVisible()) { - this.collapseAllAction.enabled = this.markersModel.hasFilteredResources(); - dom.toggleClass(this.treeContainer, 'hidden', !this.markersModel.hasFilteredResources()); + this.collapseAllAction.enabled = this.markersWorkbenchService.markersModel.hasFilteredResources(); + dom.toggleClass(this.treeContainer, 'hidden', !this.markersWorkbenchService.markersModel.hasFilteredResources()); this.renderMessage(); - if (this.markersModel.hasFilteredResources()) { + if (this.markersWorkbenchService.markersModel.hasFilteredResources()) { return this.tree.refresh().then(() => { this.autoExpand(); }); @@ -187,19 +178,12 @@ export class MarkersPanel extends Panel { } public updateFilter(filter: string) { - this.markersModel.update(new FilterOptions(filter)); + this.markersWorkbenchService.filter(filter); this.autoExpanded = new Set(); this.refreshPanel(); this.autoReveal(); } - private refreshBadge(): void { - const total = this.markersModel.total(); - const count = this.markersModel.count(); - const message = total === count ? localize('totalProblems', 'Total {0} Problems', total) : localize('filteredProblems', 'Showing {0} of {1} Problems', count, total); - this.activityService.showActivity(this.getId(), new NumberBadge(count, () => message)); - } - private createMessageBox(parent: HTMLElement): void { this.messageBoxContainer = dom.append(parent, dom.$('.message-box-container')); this.messageBox = dom.append(this.messageBoxContainer, dom.$('span')); @@ -247,7 +231,7 @@ export class MarkersPanel extends Panel { } private createListeners(): void { - this.toUnbind.push(this.markerService.onMarkerChanged(this.onMarkerChanged, this)); + this.toUnbind.push(this.markersWorkbenchService.onDidChangeMarkersForResources(this.onMarkerChanged, this)); this.toUnbind.push(this.editorGroupService.onEditorsChanged(this.onEditorsChanged, this)); this.toUnbind.push(this.tree.onDidChangeSelection(() => this.onSelected())); } @@ -290,34 +274,29 @@ export class MarkersPanel extends Panel { } private updateResources(resources: URI[]) { - const bulkUpdater = this.markersModel.getBulkUpdater(); for (const resource of resources) { - bulkUpdater.add(resource, this.markerService.read({ resource })); - } - bulkUpdater.done(); - for (const resource of resources) { - if (!this.markersModel.hasResource(resource)) { + if (!this.markersWorkbenchService.markersModel.hasResource(resource)) { this.autoExpanded.delete(resource.toString()); } } } - private render(): void { - let allMarkers = this.markerService.read(); - this.markersModel.update(allMarkers); - this.tree.setInput(this.markersModel).then(this.autoExpand.bind(this)); - dom.toggleClass(this.treeContainer, 'hidden', !this.markersModel.hasFilteredResources()); - this.renderMessage(); + private render(): TPromise { + dom.toggleClass(this.treeContainer, 'hidden', !this.markersWorkbenchService.markersModel.hasFilteredResources()); + return this.tree.setInput(this.markersWorkbenchService.markersModel) + .then(() => { + this.renderMessage(); + this.autoExpand(); + }); } private renderMessage(): void { - let message = this.markersModel.getMessage(); - this.messageBox.textContent = message; - dom.toggleClass(this.messageBoxContainer, 'hidden', this.markersModel.hasFilteredResources()); + this.messageBox.textContent = this.markersWorkbenchService.markersModel.getMessage(); + dom.toggleClass(this.messageBoxContainer, 'hidden', this.markersWorkbenchService.markersModel.hasFilteredResources()); } private autoExpand(): void { - for (const resource of this.markersModel.filteredResources) { + for (const resource of this.markersWorkbenchService.markersModel.filteredResources) { const resourceUri = resource.uri.toString(); if (!this.autoExpanded.has(resourceUri)) { this.tree.expand(resource).done(null, errors.onUnexpectedError); @@ -356,7 +335,7 @@ export class MarkersPanel extends Panel { private getResourceForCurrentActiveResource(): Resource { if (this.currentActiveResource) { - let resources = this.markersModel.filteredResources.filter((resource): boolean => { + let resources = this.markersWorkbenchService.markersModel.filteredResources.filter((resource): boolean => { return this.currentActiveResource.toString() === resource.uri.toString(); }); return resources.length > 0 ? resources[0] : null; @@ -407,6 +386,5 @@ export class MarkersPanel extends Panel { this.delayedRefresh.cancel(); this.tree.dispose(); - this.markersModel.dispose(); } } diff --git a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts index 03c6c2a3c174a510e8a052bffa1122000e6a482d..cf62c96da0fa28064817735b224d543c097493af 100644 --- a/src/vs/workbench/parts/markers/browser/markersPanelActions.ts +++ b/src/vs/workbench/parts/markers/browser/markersPanelActions.ts @@ -24,6 +24,7 @@ import { CollapseAllAction as TreeCollapseAction } from 'vs/base/parts/tree/brow import Tree = require('vs/base/parts/tree/browser/tree'); import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; +import { IMarkersWorkbenchService } from 'vs/workbench/parts/markers/common/markers'; export class ToggleMarkersPanelAction extends TogglePanelAction { @@ -80,6 +81,7 @@ export class FilterInputBoxActionItem extends BaseActionItem { constructor(private markersPanel: MarkersPanel, action: IAction, @IContextViewService private contextViewService: IContextViewService, @IThemeService private themeService: IThemeService, + @IMarkersWorkbenchService private markersWorkbenchService: IMarkersWorkbenchService, @ITelemetryService private telemetryService: ITelemetryService) { super(markersPanel, action); this.toDispose = []; @@ -93,7 +95,7 @@ export class FilterInputBoxActionItem extends BaseActionItem { ariaLabel: Messages.MARKERS_PANEL_FILTER_PLACEHOLDER }); this.toDispose.push(attachInputBoxStyler(filterInputBox, this.themeService)); - filterInputBox.value = this.markersPanel.markersModel.filterOptions.completeFilter; + filterInputBox.value = this.markersWorkbenchService.markersModel.filterOptions.completeFilter; this.toDispose.push(filterInputBox.onDidChange(filter => this.delayedFilterUpdate.trigger(() => this.updateFilter(filter)))); this.toDispose.push(DOM.addStandardDisposableListener(filterInputBox.inputElement, 'keyup', (keyboardEvent) => this.onInputKeyUp(keyboardEvent, filterInputBox))); this.toDispose.push(DOM.addStandardDisposableListener(container, 'keydown', this.handleKeyboardEvent)); @@ -107,9 +109,9 @@ export class FilterInputBoxActionItem extends BaseActionItem { private reportFilteringUsed(): void { let data = {}; - data['errors'] = this.markersPanel.markersModel.filterOptions.filterErrors; - data['warnings'] = this.markersPanel.markersModel.filterOptions.filterWarnings; - data['infos'] = this.markersPanel.markersModel.filterOptions.filterInfos; + data['errors'] = this.markersWorkbenchService.markersModel.filterOptions.filterErrors; + data['warnings'] = this.markersWorkbenchService.markersModel.filterOptions.filterWarnings; + data['infos'] = this.markersWorkbenchService.markersModel.filterOptions.filterInfos; /* __GDPR__ "problems.filter" : { "errors" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, diff --git a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts index 5d31a4a46c6842c2432d70c751b8f05c95c79cde..70489480afaa8f547b938bb8f8e114e74aee405c 100644 --- a/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts +++ b/src/vs/workbench/parts/markers/browser/markersWorkbenchContributions.ts @@ -16,9 +16,13 @@ import { ToggleMarkersPanelAction, ShowProblemsPanelAction } from 'vs/workbench/ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { MarkersPanel } from 'vs/workbench/parts/markers/browser/markersPanel'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IMarkersWorkbenchService, MarkersWorkbenchService } from 'vs/workbench/parts/markers/common/markers'; export function registerContributions(): void { + registerSingleton(IMarkersWorkbenchService, MarkersWorkbenchService); + KeybindingsRegistry.registerCommandAndKeybindingRule({ id: Constants.MARKER_OPEN_SIDE_ACTION_ID, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), diff --git a/src/vs/workbench/parts/markers/common/markers.ts b/src/vs/workbench/parts/markers/common/markers.ts new file mode 100644 index 0000000000000000000000000000000000000000..f86fee2b300f3290d7143f612554bcf5551bbfb9 --- /dev/null +++ b/src/vs/workbench/parts/markers/common/markers.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { MarkersModel, FilterOptions } from 'vs/workbench/parts/markers/common/markersModel'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IMarkerService } from 'vs/platform/markers/common/markers'; +import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity'; +import { localize } from 'vs/nls'; +import Constants from 'vs/workbench/parts/markers/common/constants'; +import URI from 'vs/base/common/uri'; +import Event, { Emitter } from 'vs/base/common/event'; + +export const IMarkersWorkbenchService = createDecorator('markersWorkbenchService'); + +export interface IMarkersWorkbenchService { + _serviceBrand: any; + + readonly onDidChangeMarkersForResources: Event; + readonly markersModel: MarkersModel; + + filter(filter: string): void; +} + +export class MarkersWorkbenchService extends Disposable implements IMarkersWorkbenchService { + _serviceBrand: any; + + readonly markersModel: MarkersModel; + + private readonly _onDidChangeMarkersForResources: Emitter = this._register(new Emitter()); + readonly onDidChangeMarkersForResources: Event = this._onDidChangeMarkersForResources.event; + + constructor( + @IMarkerService private markerService: IMarkerService, + @IActivityService private activityService: IActivityService + ) { + super(); + this.markersModel = this._register(new MarkersModel(this.markerService.read())); + this._register(markerService.onMarkerChanged(resources => this.onMarkerChanged(resources))); + } + + filter(filter: string): void { + this.markersModel.update(new FilterOptions(filter)); + this.refreshBadge(); + } + + private onMarkerChanged(resources: URI[]): void { + const bulkUpdater = this.markersModel.getBulkUpdater(); + for (const resource of resources) { + bulkUpdater.add(resource, this.markerService.read({ resource })); + } + bulkUpdater.done(); + this.refreshBadge(); + this._onDidChangeMarkersForResources.fire(resources); + } + + private refreshBadge(): void { + const total = this.markersModel.total(); + const count = this.markersModel.count(); + const message = total === count ? localize('totalProblems', 'Total {0} Problems', total) : localize('filteredProblems', 'Showing {0} of {1} Problems', count, total); + this.activityService.showActivity(Constants.MARKERS_PANEL_ID, new NumberBadge(count, () => message)); + } +} \ No newline at end of file