Skip to content

Commit

Permalink
Use a menu instead of hard coding actions in tabsWidget (microsoft#12…
Browse files Browse the repository at this point in the history
  • Loading branch information
meganrogge authored Apr 28, 2021
1 parent 1f165be commit f727e50
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 32 deletions.
1 change: 1 addition & 0 deletions src/vs/platform/actions/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export class MenuId {
static readonly TerminalTabsWidgetContext = new MenuId('TerminalTabsWidgetContext');
static readonly TerminalTabsWidgetEmptyContext = new MenuId('TerminalTabsWidgetEmptyContext');
static readonly TerminalSingleTabContext = new MenuId('TerminalSingleTabContext');
static readonly TerminalTabInlineActions = new MenuId('TerminalTabInlineActions');

readonly id: number;
readonly _debugName: string;
Expand Down
25 changes: 23 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminalActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ export function registerTerminalActions() {
constructor() {
super({
id: TERMINAL_COMMAND_ID.SPLIT_INSTANCE,
title: { value: localize('workbench.action.terminal.split', "Split Terminal"), original: 'Split Terminal' },
title: { value: localize('workbench.action.terminal.splitInstance', "Split Terminal"), original: 'Split Terminal' },
f1: false,
category,
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED,
Expand Down Expand Up @@ -1422,6 +1422,13 @@ export function registerTerminalActions() {
}
}
});
MenuRegistry.appendMenuItem(MenuId.TerminalTabInlineActions, {
command: {
id: TERMINAL_COMMAND_ID.SPLIT_INSTANCE,
title: localize('workbench.action.terminal.splitInstance', "Split Terminal"),
},
group: ContextMenuGroup.Create
});
registerAction2(class extends Action2 {
constructor() {
super({
Expand Down Expand Up @@ -1586,7 +1593,7 @@ export function registerTerminalActions() {
super({
id: TERMINAL_COMMAND_ID.KILL_INSTANCE,
title: {
value: localize('workbench.action.terminal.kill.short', "Kill Terminal"), original: 'Kill Terminal'
value: localize('workbench.action.terminal.killInstance', "Kill Terminal"), original: 'Kill Terminal'
},
f1: false,
category,
Expand All @@ -1608,8 +1615,17 @@ export function registerTerminalActions() {
}
async run(accessor: ServicesAccessor) {
getSelectedInstances(accessor)?.forEach(instance => instance.dispose(true));
accessor.get(ITerminalService).focusTabs();
focusNext(accessor);
}
});
MenuRegistry.appendMenuItem(MenuId.TerminalTabInlineActions, {
command: {
id: TERMINAL_COMMAND_ID.KILL_INSTANCE,
title: localize('workbench.action.terminal.killInstance', "Kill Terminal")
},
group: ContextMenuGroup.Kill
});
registerAction2(class extends Action2 {
constructor() {
super({
Expand Down Expand Up @@ -1889,3 +1905,8 @@ function getSelectedInstances(accessor: ServicesAccessor): ITerminalInstance[] |
}
return instances;
}

function focusNext(accessor: ServicesAccessor): void {
const listService = accessor.get(IListService);
listService.lastFocusedList?.focusNext();
}
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ export class TerminalService implements ITerminalService {
const newIndex = index < this._terminalTabs.length ? index : this._terminalTabs.length - 1;
this.setActiveTabByIndex(newIndex);
const activeInstance = this.getActiveInstance();
if (activeInstance) {
if (this._onActiveInstanceChanged && activeInstance?.hadFocusOnExit) {
activeInstance.focus(true);
}
} else if (activeTabIndex >= this._terminalTabs.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ export class TerminalTabbedView extends Disposable {
this._instanceMenu = this._register(menuService.createMenu(MenuId.TerminalContainerContext, contextKeyService));
this._tabsWidgetMenu = this._register(menuService.createMenu(MenuId.TerminalTabsWidgetContext, contextKeyService));
this._tabsWidgetEmptyMenu = this._register(menuService.createMenu(MenuId.TerminalTabsWidgetEmptyContext, contextKeyService));
const inlineMenu = this._register(menuService.createMenu(MenuId.TerminalTabInlineActions, contextKeyService));

this._register(this._tabsWidget = this._instantiationService.createInstance(TerminalTabsWidget, this._terminalTabTree));
this._register(this._tabsWidget = this._instantiationService.createInstance(TerminalTabsWidget, this._terminalTabTree, inlineMenu));
this._register(this._findWidget = this._instantiationService.createInstance(TerminalFindWidget, this._terminalService.getFindState()));
parentElement.appendChild(this._findWidget.getDomNode());

Expand Down
40 changes: 12 additions & 28 deletions src/vs/workbench/contrib/terminal/browser/terminalTabsWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { localize } from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { MenuItemAction } from 'vs/platform/actions/common/actions';
import { IMenu, MenuItemAction } from 'vs/platform/actions/common/actions';
import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal';
import { Codicon } from 'vs/base/common/codicons';
import { Action } from 'vs/base/common/actions';
import { MarkdownString } from 'vs/base/common/htmlContent';
import { TerminalDecorationsProvider } from 'vs/workbench/contrib/terminal/browser/terminalDecorationsProvider';
import { DEFAULT_LABELS_CONTAINER, IResourceLabel, ResourceLabels } from 'vs/workbench/browser/labels';
import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
import { IHoverAction, IHoverService } from 'vs/workbench/services/hover/browser/hover';
import Severity from 'vs/base/common/severity';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { Codicon } from 'vs/base/common/codicons';

const $ = DOM.$;
const TAB_HEIGHT = 22;
Expand All @@ -41,6 +40,7 @@ export class TerminalTabsWidget extends WorkbenchObjectTree<ITerminalInstance>

constructor(
container: HTMLElement,
inlineMenu: IMenu,
@IContextKeyService contextKeyService: IContextKeyService,
@IListService listService: IListService,
@IThemeService themeService: IThemeService,
Expand All @@ -56,7 +56,7 @@ export class TerminalTabsWidget extends WorkbenchObjectTree<ITerminalInstance>
getHeight: () => TAB_HEIGHT,
getTemplateId: () => 'terminal.tabs'
},
[instantiationService.createInstance(TerminalTabsRenderer, container, instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER), () => this.getSelection())],
[instantiationService.createInstance(TerminalTabsRenderer, container, inlineMenu, instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER))],
{
horizontalScrolling: false,
supportDynamicHeights: false,
Expand Down Expand Up @@ -162,11 +162,10 @@ export class TerminalTabsWidget extends WorkbenchObjectTree<ITerminalInstance>

class TerminalTabsRenderer implements ITreeRenderer<ITerminalInstance, never, ITerminalTabEntryTemplate> {
templateId = 'terminal.tabs';

constructor(
private readonly _container: HTMLElement,
private readonly _inlineMenu: IMenu,
private readonly _labels: ResourceLabels,
private readonly _getSelection: () => (ITerminalInstance | null)[],
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITerminalService private readonly _terminalService: ITerminalService,
@IHoverService private readonly _hoverService: IHoverService,
Expand Down Expand Up @@ -328,31 +327,16 @@ class TerminalTabsRenderer implements ITreeRenderer<ITerminalInstance, never, IT

fillActionBar(instance: ITerminalInstance, template: ITerminalTabEntryTemplate): void {
// If the instance is within the selection, split all selected
const actions = [
new Action(TERMINAL_COMMAND_ID.SPLIT_INSTANCE, localize('terminal.split', "Split"), ThemeIcon.asClassName(Codicon.splitHorizontal), true, async () => {
this._runForSelectionOrInstance(instance, e => this._terminalService.splitInstance(e));
}),
new Action(TERMINAL_COMMAND_ID.KILL_INSTANCE, localize('terminal.kill', "Kill"), ThemeIcon.asClassName(Codicon.trashcan), true, async () => {
this._runForSelectionOrInstance(instance, e => e.dispose());
})
];
const actions = this._inlineMenu.getActions();
// TODO: Cache these in a way that will use the correct instance
template.actionBar.clear();
for (const action of actions) {
template.actionBar.push(action, { icon: true, label: false, keybinding: this._keybindingService.lookupKeybinding(action.id)?.getLabel() });
}
}

private _runForSelectionOrInstance(instance: ITerminalInstance, callback: (instance: ITerminalInstance) => void) {
const selection = this._getSelection();
if (selection.includes(instance)) {
for (const s of selection) {
if (s) {
callback(s);
for (const [, action] of actions) {
for (const a of action) {
a.item.icon = a.id === TERMINAL_COMMAND_ID.KILL_INSTANCE ? Codicon.trashcan : Codicon.splitHorizontal;
if ('item' in a) {
template.actionBar.push(a, { icon: true, label: false, keybinding: this._keybindingService.lookupKeybinding(a.id)?.getLabel() });
}
}
} else {
callback(instance);
}
}
}
Expand Down

0 comments on commit f727e50

Please sign in to comment.