From 3444dd91a67f33686a960d4446dd802e4ed2b587 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Wed, 4 Mar 2020 15:54:45 -0500 Subject: [PATCH] Adds timeline filter context menu --- .../contrib/timeline/browser/timelinePane.ts | 108 +++++++----------- .../contrib/timeline/common/timeline.ts | 7 +- .../timeline/common/timelineService.ts | 2 +- 3 files changed, 50 insertions(+), 67 deletions(-) diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 9c5881e6e64..4f91deaa1ec 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -18,23 +18,23 @@ import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/vie import { ResourceNavigator, WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITimelineService, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvidersChangeEvent, TimelineRequest, Timeline, TimelinePaneId } from 'vs/workbench/contrib/timeline/common/timeline'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { SideBySideEditor, toResource } from 'vs/workbench/common/editor'; -import { ICommandService, CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; +import { ICommandService } from 'vs/platform/commands/common/commands'; import { IThemeService, LIGHT, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { basename } from 'vs/base/common/path'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { debounce } from 'vs/base/common/decorators'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IActionViewItemProvider, ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IAction, ActionRunner } from 'vs/base/common/actions'; +import { IActionViewItemProvider, ActionBar, ActionViewItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IAction, ActionRunner, Action } from 'vs/base/common/actions'; import { ContextAwareMenuEntryActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { MenuItemAction, IMenuService, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; +import { MenuItemAction, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { fromNow } from 'vs/base/common/date'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -85,8 +85,6 @@ interface TimelineCursors { more: boolean; } -export const TimelineFollowActiveEditorContext = new RawContextKey('timelineFollowActiveEditor', true); - export class TimelinePane extends ViewPane { static readonly TITLE = localize('timeline', 'Timeline'); @@ -99,8 +97,6 @@ export class TimelinePane extends ViewPane { private _menus: TimelinePaneMenus; private _visibilityDisposables: DisposableStore | undefined; - private _followActiveEditorContext: IContextKey; - private _excludedSources: Set; private _cursorsByProvider: Map = new Map(); private _items: { element: TreeElement }[] = []; @@ -126,13 +122,10 @@ export class TimelinePane extends ViewPane { super({ ...options, titleMenuId: MenuId.TimelineTitle }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); this._menus = this._register(this.instantiationService.createInstance(TimelinePaneMenus, this.id)); - this._register(this.instantiationService.createInstance(TimelinePaneCommands, this)); const scopedContextKeyService = this._register(this.contextKeyService.createScoped()); scopedContextKeyService.createKey('view', TimelinePaneId); - this._followActiveEditorContext = TimelineFollowActiveEditorContext.bindTo(this.contextKeyService); - this._excludedSources = new Set(configurationService.getValue('timeline.excludeSources')); configurationService.onDidChangeConfiguration(this.onConfigurationChanged, this); @@ -149,7 +142,7 @@ export class TimelinePane extends ViewPane { } this._followActiveEditor = value; - this._followActiveEditorContext.set(value); + this.updateActions(); if (value) { this.onActiveEditorChanged(); @@ -180,6 +173,7 @@ export class TimelinePane extends ViewPane { } this._excludedSources = new Set(this.configurationService.getValue('timeline.excludeSources')); + this.updateActions(); this.loadTimeline(true); } @@ -205,6 +199,8 @@ export class TimelinePane extends ViewPane { } private onProvidersChanged(e: TimelineProvidersChangeEvent) { + this.updateActions(); + if (e.removed) { for (const source of e.removed) { this.replaceItems(source); @@ -305,7 +301,7 @@ export class TimelinePane extends ViewPane { return; } - const filteredSources = (sources ?? this.timelineService.getSources()).filter(s => !this._excludedSources.has(s)); + const filteredSources = (sources ?? this.timelineService.getSources().map(s => s.id)).filter(s => !this._excludedSources.has(s)); if (filteredSources.length === 0) { if (reset) { this.refresh(); @@ -603,6 +599,39 @@ export class TimelinePane extends ViewPane { this.refresh(); } + getActions(): IAction[] { + return [ + ...super.getActions(), + this.followActiveEditor + ? new Action('toggleFollowActiveEditorCommand', localize('timeline.toggleFollowActiveEditorCommand.stop', "Stop following the Active Editor"), 'explorer-action codicon-eye', true, () => Promise.resolve(this.followActiveEditor = !this.followActiveEditor)) + : new Action('toggleFollowActiveEditorCommand', localize('timeline.toggleFollowActiveEditorCommand.follow', "Follow the Active Editor"), 'explorer-action codicon-eye-closed', true, () => Promise.resolve(this.followActiveEditor = !this.followActiveEditor)), + new Action('refresh', localize('refresh', "Refresh"), 'explorer-action codicon-refresh', true, () => Promise.resolve(this.reset())), + ]; + } + + getSecondaryActions(): IAction[] { + const actions: IAction[] = [new Separator()]; + + const excluded = new Set(this._excludedSources); + + for (const source of this.timelineService.getSources()) { + const action = new Action(`filter:${source.id}`, localize('timeline.filterSource', "Include: {0}", source.label), undefined, true, () => { + if (excluded.has(source.id)) { + excluded.delete(source.id); + } else { + excluded.add(source.id); + } + this.configurationService.updateValue('timeline.excludeSources', [...excluded.keys()]); + return Promise.resolve(); + }); + action.checked = !excluded.has(source.id); + + actions.push(action); + } + + return [...super.getSecondaryActions(), ...actions]; + } + focus(): void { super.focus(); this._tree.domFocus(); @@ -895,57 +924,6 @@ class TimelineTreeRenderer implements ITreeRenderer this._pane.reset(); - } - - toggleFollowActiveEditorCommand(): ICommandHandler { - return (accessor, arg) => this._pane.followActiveEditor = !this._pane.followActiveEditor; - } -} - class TimelinePaneMenus extends Disposable { constructor( diff --git a/src/vs/workbench/contrib/timeline/common/timeline.ts b/src/vs/workbench/contrib/timeline/common/timeline.ts index d9e4720eb00..6555bc8deb6 100644 --- a/src/vs/workbench/contrib/timeline/common/timeline.ts +++ b/src/vs/workbench/contrib/timeline/common/timeline.ts @@ -69,6 +69,11 @@ export interface TimelineProvider extends TimelineProviderDescriptor, IDisposabl provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions): Promise; } +export interface TimelineSource { + id: string; + label: string; +} + export interface TimelineProviderDescriptor { id: string; label: string; @@ -98,7 +103,7 @@ export interface ITimelineService { registerTimelineProvider(provider: TimelineProvider): IDisposable; unregisterTimelineProvider(id: string): void; - getSources(): string[]; + getSources(): TimelineSource[]; getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: InternalTimelineOptions): TimelineRequest | undefined; diff --git a/src/vs/workbench/contrib/timeline/common/timelineService.ts b/src/vs/workbench/contrib/timeline/common/timelineService.ts index fc996a3d8c5..5d2b7242c50 100644 --- a/src/vs/workbench/contrib/timeline/common/timelineService.ts +++ b/src/vs/workbench/contrib/timeline/common/timelineService.ts @@ -98,7 +98,7 @@ export class TimelineService implements ITimelineService { } getSources() { - return [...this._providers.keys()]; + return [...this._providers.values()].map(p => ({ id: p.id, label: p.label })); } getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: InternalTimelineOptions) { -- GitLab