From d9bfe033f599f0c77d69e09795b81fb810a3d24f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 19 Dec 2018 18:55:28 +0100 Subject: [PATCH] labels - visibility --- src/vs/workbench/browser/labels.ts | 44 ++++++++++++++++++- .../browser/parts/views/customView.ts | 13 +++++- .../electron-browser/commentsPanel.ts | 15 +++++-- .../parts/debug/browser/loadedScriptsView.ts | 16 +++++-- .../electron-browser/views/explorerView.ts | 8 ++++ .../electron-browser/views/openEditorsView.ts | 19 +++++--- .../markers/electron-browser/markersPanel.ts | 13 +++++- .../parts/scm/electron-browser/scmViewlet.ts | 20 +++++++-- .../parts/search/browser/searchView.ts | 16 +++++-- 9 files changed, 137 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/browser/labels.ts b/src/vs/workbench/browser/labels.ts index 6bc8cf35fad..3742b85b8be 100644 --- a/src/vs/workbench/browser/labels.ts +++ b/src/vs/workbench/browser/labels.ts @@ -67,6 +67,9 @@ export interface IResourceLabel extends IDisposable { */ setEditor(editor: IEditorInput, options?: IResourceLabelOptions): void; + /** + * Resets the label to be empty. + */ clear(): void; } @@ -103,7 +106,7 @@ export class ResourceLabels extends Disposable { this._register(this.decorationsService.onDidChangeDecorations(e => this._widgets.forEach(widget => widget.notifyFileDecorationsChanges(e)))); // notify when theme changes - this._register(this.themeService.onThemeChange(() => () => this._widgets.forEach(widget => widget.notifyThemeChange()))); + this._register(this.themeService.onThemeChange(() => this._widgets.forEach(widget => widget.notifyThemeChange()))); // notify when files.associations changes this._register(this.configurationService.onDidChangeConfiguration(e => { @@ -145,6 +148,14 @@ export class ResourceLabels extends Disposable { dispose(widget); } + onVisible(): void { + this._widgets.forEach(widget => widget.notifyVisibilityChanged(true)); + } + + onHidden(): void { + this._widgets.forEach(widget => widget.notifyVisibilityChanged(false)); + } + clear(): void { this._widgets = dispose(this._widgets); this._labels = []; @@ -186,6 +197,11 @@ export class ResourceLabel extends ResourceLabels { } } +enum Redraw { + Basic = 1, + Full = 2 +} + class ResourceLabelWidget extends IconLabel { private _onDidRender = this._register(new Emitter()); @@ -197,6 +213,9 @@ class ResourceLabelWidget extends IconLabel { private lastKnownConfiguredLangId: string; private computedPathLabel: string; + private needsRedraw: Redraw; + private isHidden: boolean = false; + constructor( container: HTMLElement, options: IIconLabelCreationOptions, @@ -210,6 +229,17 @@ class ResourceLabelWidget extends IconLabel { super(container, options); } + notifyVisibilityChanged(visible: boolean): void { + if (visible === this.isHidden) { + this.isHidden = !visible; + + if (visible && this.needsRedraw) { + this.render(this.needsRedraw === Redraw.Basic ? false : true); + this.needsRedraw = void 0; + } + } + } + notifyModelModeChanged(e: { model: ITextModel; oldModeId: string; }): void { if (!this.label || !this.label.resource) { return; // only update if label exists @@ -335,6 +365,18 @@ class ResourceLabelWidget extends IconLabel { } private render(clearIconCache: boolean): void { + if (this.isHidden) { + if (!this.needsRedraw) { + this.needsRedraw = clearIconCache ? Redraw.Full : Redraw.Basic; + } + + if (this.needsRedraw === Redraw.Basic && clearIconCache) { + this.needsRedraw = Redraw.Full; + } + + return; + } + if (this.label) { const configuredLangId = getConfiguredLangId(this.modelService, this.label.resource); if (this.lastKnownConfiguredLangId !== configuredLangId) { diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index b5e17c96d71..cb4dd721cc4 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -194,6 +194,7 @@ export class CustomTreeView extends Disposable implements ITreeView { private _messageValue: string | IMarkdownString | undefined; private messageElement: HTMLDivElement; private tree: FileIconThemableWorkbenchTree; + private treeLabels: ResourceLabels; private root: ITreeItem; private elementsToRefresh: ITreeItem[] = []; private menus: TitleMenus; @@ -349,6 +350,14 @@ export class CustomTreeView extends Disposable implements ITreeView { } } + if (this.treeLabels) { + if (this.isVisible) { + this.treeLabels.onVisible(); + } else { + this.treeLabels.onHidden(); + } + } + this._onDidChangeVisibility.fire(this.isVisible); } @@ -383,9 +392,9 @@ export class CustomTreeView extends Disposable implements ITreeView { private createTree() { const actionItemProvider = (action: IAction) => action instanceof MenuItemAction ? this.instantiationService.createInstance(ContextAwareMenuItemActionItem, action) : undefined; const menus = this._register(this.instantiationService.createInstance(TreeMenus, this.id)); - const labels = this._register(this.instantiationService.createInstance(ResourceLabels)); + this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels)); const dataSource = this.instantiationService.createInstance(TreeDataSource, this, this.container); - const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, labels, actionItemProvider); + const renderer = this.instantiationService.createInstance(TreeRenderer, this.id, menus, this.treeLabels, actionItemProvider); const controller = this.instantiationService.createInstance(TreeController, this.id, menus); this.tree = this._register(this.instantiationService.createInstance(FileIconThemableWorkbenchTree, this.treeContainer, { dataSource, renderer, controller }, {})); this.tree.contextKeyService.createKey(this.id, true); diff --git a/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts b/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts index b2423f8c6a3..35552bea79c 100644 --- a/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts +++ b/src/vs/workbench/parts/comments/electron-browser/commentsPanel.ts @@ -29,7 +29,7 @@ export const COMMENTS_PANEL_ID = 'workbench.panel.comments'; export const COMMENTS_PANEL_TITLE = 'Comments'; export class CommentsPanel extends Panel { - private labels: ResourceLabels; + private treeLabels: ResourceLabels; private tree: WorkbenchTree; private treeContainer: HTMLElement; private messageBoxContainer: HTMLElement; @@ -131,11 +131,11 @@ export class CommentsPanel extends Panel { } private createTree(): void { - this.labels = this._register(this.instantiationService.createInstance(ResourceLabels)); + this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels)); this.tree = this._register(this.instantiationService.createInstance(WorkbenchTree, this.treeContainer, { dataSource: new CommentsDataSource(), - renderer: new CommentsModelRenderer(this.labels, this.openerService), + renderer: new CommentsModelRenderer(this.treeLabels, this.openerService), accessibilityProvider: new DefaultAccessibilityProvider, controller: new DefaultController(), dnd: new DefaultDragAndDrop(), @@ -176,7 +176,6 @@ export class CommentsPanel extends Panel { return true; } - const threadToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].threadId : element.threadId; const commentToReveal = element instanceof ResourceWithCommentThreads ? element.commentThreads[0].comment : element.comment; @@ -241,6 +240,14 @@ export class CommentsPanel extends Panel { this.refresh(); } } + + if (this.treeLabels) { + if (visible) { + this.treeLabels.onVisible(); + } else { + this.treeLabels.onHidden(); + } + } } private refresh(): void { diff --git a/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts b/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts index 743369b4882..9decf3c88c3 100644 --- a/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts +++ b/src/vs/workbench/parts/debug/browser/loadedScriptsView.ts @@ -364,10 +364,10 @@ export class LoadedScriptsView extends ViewletPanel { private treeContainer: HTMLElement; private loadedScriptsItemType: IContextKey; private tree: WorkbenchAsyncDataTree; + private treeLabels: ResourceLabels; private changeScheduler: RunOnceScheduler; private treeNeedsRefreshOnVisible: boolean; private filter: LoadedScriptsFilter; - private labels: ResourceLabels; constructor( options: IViewletViewOptions, @@ -397,10 +397,11 @@ export class LoadedScriptsView extends ViewletPanel { const root = new RootTreeItem(this.debugService.getModel(), this.environmentService, this.contextService); - this.labels = this.instantiationService.createInstance(ResourceLabels); + this.treeLabels = this.instantiationService.createInstance(ResourceLabels); + this.disposables.push(this.treeLabels); this.tree = new WorkbenchAsyncDataTree(this.treeContainer, new LoadedScriptsDelegate(), - [new LoadedScriptsRenderer(this.labels)], + [new LoadedScriptsRenderer(this.treeLabels)], new LoadedScriptsDataSource(), { identityProvider: { @@ -509,6 +510,13 @@ export class LoadedScriptsView extends ViewletPanel { if (visible && this.treeNeedsRefreshOnVisible) { this.changeScheduler.schedule(); } + if (this.treeLabels) { + if (visible) { + this.treeLabels.onVisible(); + } else { + this.treeLabels.onHidden(); + } + } } /* @@ -521,7 +529,7 @@ export class LoadedScriptsView extends ViewletPanel { dispose(): void { this.tree = dispose(this.tree); - this.labels = dispose(this.labels); + this.treeLabels = dispose(this.treeLabels); super.dispose(); } } diff --git a/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts b/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts index 889411a3949..4a56d682290 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/explorerView.ts @@ -373,6 +373,14 @@ export class ExplorerView extends TreeViewsViewletPanel implements IExplorerView this.openFocusedElement(); }); } + + if (this.explorerLabels) { + if (visible) { + this.explorerLabels.onVisible(); + } else { + this.explorerLabels.onHidden(); + } + } } private openFocusedElement(preserveFocus?: boolean): void { diff --git a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts index b1b4c6d16dc..dee98bd96ea 100644 --- a/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts +++ b/src/vs/workbench/parts/files/electron-browser/views/openEditorsView.ts @@ -51,7 +51,7 @@ export class OpenEditorsView extends ViewletPanel { private listRefreshScheduler: RunOnceScheduler; private structuralRefreshDelay: number; private list: WorkbenchList; - private labels: ResourceLabels; + private listLabels: ResourceLabels; private contributedContextMenu: IMenu; private needsRefresh: boolean; private resourceContext: ResourceContextKey; @@ -214,19 +214,19 @@ export class OpenEditorsView extends ViewletPanel { if (this.list) { this.list.dispose(); } - if (this.labels) { - this.labels.clear(); + if (this.listLabels) { + this.listLabels.clear(); } - this.labels = this.instantiationService.createInstance(ResourceLabels); + this.listLabels = this.instantiationService.createInstance(ResourceLabels); this.list = this.instantiationService.createInstance(WorkbenchList, container, delegate, [ new EditorGroupRenderer(this.keybindingService, this.instantiationService, this.editorGroupService), - new OpenEditorRenderer(this.labels, getSelectedElements, this.instantiationService, this.keybindingService, this.configurationService, this.editorGroupService) + new OpenEditorRenderer(this.listLabels, getSelectedElements, this.instantiationService, this.keybindingService, this.configurationService, this.editorGroupService) ], { identityProvider: { getId: (element: OpenEditor | IEditorGroup) => element instanceof OpenEditor ? element.getId() : element.id.toString() }, selectOnMouseDown: false /* disabled to better support DND */ }) as WorkbenchList; this.disposables.push(this.list); - this.disposables.push(this.labels); + this.disposables.push(this.listLabels); this.contributedContextMenu = this.menuService.createMenu(MenuId.OpenEditorsContext, this.list.contextKeyService); this.disposables.push(this.contributedContextMenu); @@ -333,6 +333,13 @@ export class OpenEditorsView extends ViewletPanel { dom.hide(this.list.getHTMLElement()); // make sure the list goes out of the tabindex world by hiding it } } + if (this.listLabels) { + if (isVisible) { + this.listLabels.onVisible(); + } else { + this.listLabels.onHidden(); + } + } } private get showGroups(): boolean { diff --git a/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts index 2787c86c2f2..bbb5f94b349 100644 --- a/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts +++ b/src/vs/workbench/parts/markers/electron-browser/markersPanel.ts @@ -67,6 +67,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { private currentActiveResource: URI | null = null; private tree: WorkbenchObjectTree; + private treeLabels: ResourceLabels; private rangeHighlightDecorations: RangeHighlightDecorations; private actions: IAction[]; @@ -171,6 +172,14 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { } else { this.rangeHighlightDecorations.removeHighlightRange(); } + + if (this.treeLabels) { + if (visible) { + this.treeLabels.onVisible(); + } else { + this.treeLabels.onHidden(); + } + } } public getActions(): IAction[] { @@ -288,11 +297,11 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { const onDidChangeRenderNodeCount = new Relay>(); - const labels = this._register(this.instantiationService.createInstance(ResourceLabels)); + this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels)); const virtualDelegate = new VirtualDelegate(this.markersViewState); const renderers = [ - this.instantiationService.createInstance(ResourceMarkersRenderer, labels, onDidChangeRenderNodeCount.event), + this.instantiationService.createInstance(ResourceMarkersRenderer, this.treeLabels, onDidChangeRenderNodeCount.event), this.instantiationService.createInstance(MarkerRenderer, this.markersViewState, a => this.getActionItem(a)), this.instantiationService.createInstance(RelatedInformationRenderer) ]; diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index 48e70ce1783..fc4462f4a32 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -728,7 +728,7 @@ export class RepositoryPanel extends ViewletPanel { private inputBox: InputBox; private listContainer: HTMLElement; private list: List; - private labels: ResourceLabels; + private listLabels: ResourceLabels; private menus: SCMMenus; private visibilityDisposables: IDisposable[] = []; protected contextKeyService: IContextKeyService; @@ -870,12 +870,12 @@ export class RepositoryPanel extends ViewletPanel { const actionItemProvider = (action: IAction) => this.getActionItem(action); - this.labels = this.instantiationService.createInstance(ResourceLabels); - this.disposables.push(this.labels); + this.listLabels = this.instantiationService.createInstance(ResourceLabels); + this.disposables.push(this.listLabels); const renderers = [ new ResourceGroupRenderer(actionItemProvider, this.themeService, this.menus), - new ResourceRenderer(this.labels, actionItemProvider, () => this.getSelectedResources(), this.themeService, this.menus) + new ResourceRenderer(this.listLabels, actionItemProvider, () => this.getSelectedResources(), this.themeService, this.menus) ]; this.list = this.instantiationService.createInstance(WorkbenchList, this.listContainer, delegate, renderers, { @@ -911,6 +911,18 @@ export class RepositoryPanel extends ViewletPanel { this.inputBox.setEnabled(this.isVisible() && this.isExpanded()); } + setVisible(visible: boolean): void { + super.setVisible(visible); + + if (this.listLabels) { + if (visible) { + this.listLabels.onVisible(); + } else { + this.listLabels.onHidden(); + } + } + } + setExpanded(expanded: boolean): void { super.setExpanded(expanded); this.inputBox.setEnabled(this.isVisible() && this.isExpanded()); diff --git a/src/vs/workbench/parts/search/browser/searchView.ts b/src/vs/workbench/parts/search/browser/searchView.ts index dcbfb928381..be55af7fa13 100644 --- a/src/vs/workbench/parts/search/browser/searchView.ts +++ b/src/vs/workbench/parts/search/browser/searchView.ts @@ -137,7 +137,7 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { private contextMenu: IMenu; private tree: WorkbenchObjectTree; - private labels: ResourceLabels; + private treeLabels: ResourceLabels; private viewletState: object; private globalMemento: object; private messagesElement: HTMLElement; @@ -586,13 +586,13 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { } }; - this.labels = this._register(this.instantiationService.createInstance(ResourceLabels)); + this.treeLabels = this._register(this.instantiationService.createInstance(ResourceLabels)); this.tree = this._register(>this.instantiationService.createInstance(WorkbenchObjectTree, this.resultsElement, delegate, [ - this._register(this.instantiationService.createInstance(FolderMatchRenderer, this.viewModel, this, this.labels)), - this._register(this.instantiationService.createInstance(FileMatchRenderer, this.viewModel, this, this.labels)), + this._register(this.instantiationService.createInstance(FolderMatchRenderer, this.viewModel, this, this.treeLabels)), + this._register(this.instantiationService.createInstance(FileMatchRenderer, this.viewModel, this, this.treeLabels)), this._register(this.instantiationService.createInstance(MatchRenderer, this.viewModel, this)), ], { @@ -769,6 +769,14 @@ export class SearchView extends Viewlet implements IViewlet, IPanel { this.onFocus(focus, true); } } + + if (this.treeLabels) { + if (visible) { + this.treeLabels.onVisible(); + } else { + this.treeLabels.onHidden(); + } + } } public moveFocusToResults(): void { -- GitLab