提交 19c999bd 编写于 作者: B Benjamin Pasero

pinned tabs - swap action for pinned tabs unless compact

上级 15e3acf6
......@@ -10,7 +10,7 @@ import * as DOM from 'vs/base/browser/dom';
import * as types from 'vs/base/common/types';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Event, Emitter } from 'vs/base/common/event';
import { Emitter } from 'vs/base/common/event';
import { IActionViewItemOptions, ActionViewItem, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
export const enum ActionsOrientation {
......@@ -47,8 +47,9 @@ export class ActionBar extends Disposable implements IActionRunner {
private _actionRunner: IActionRunner;
private _context: unknown;
private _orientation: ActionsOrientation;
private _triggerKeys: ActionTrigger;
private readonly _orientation: ActionsOrientation;
private readonly _triggerKeys: ActionTrigger;
private _actionIds: string[];
// View Items
viewItems: IActionViewItem[];
......@@ -60,16 +61,16 @@ export class ActionBar extends Disposable implements IActionRunner {
protected actionsList: HTMLElement;
private _onDidBlur = this._register(new Emitter<void>());
readonly onDidBlur: Event<void> = this._onDidBlur.event;
readonly onDidBlur = this._onDidBlur.event;
private _onDidCancel = this._register(new Emitter<void>());
readonly onDidCancel: Event<void> = this._onDidCancel.event;
readonly onDidCancel = this._onDidCancel.event;
private _onDidRun = this._register(new Emitter<IRunEvent>());
readonly onDidRun: Event<IRunEvent> = this._onDidRun.event;
readonly onDidRun = this._onDidRun.event;
private _onDidBeforeRun = this._register(new Emitter<IRunEvent>());
readonly onDidBeforeRun: Event<IRunEvent> = this._onDidBeforeRun.event;
readonly onDidBeforeRun = this._onDidBeforeRun.event;
constructor(container: HTMLElement, options: IActionBarOptions = {}) {
super();
......@@ -92,6 +93,7 @@ export class ActionBar extends Disposable implements IActionRunner {
this._register(this._actionRunner.onDidRun(e => this._onDidRun.fire(e)));
this._register(this._actionRunner.onDidBeforeRun(e => this._onDidBeforeRun.fire(e)));
this._actionIds = [];
this.viewItems = [];
this.focusedItem = undefined;
......@@ -245,6 +247,10 @@ export class ActionBar extends Disposable implements IActionRunner {
return this.domNode;
}
hasAction(action: IAction): boolean {
return this._actionIds.includes(action.id);
}
push(arg: IAction | ReadonlyArray<IAction>, options: IActionOptions = {}): void {
const actions: ReadonlyArray<IAction> = Array.isArray(arg) ? arg : [arg];
......@@ -279,9 +285,11 @@ export class ActionBar extends Disposable implements IActionRunner {
if (index === null || index < 0 || index >= this.actionsList.children.length) {
this.actionsList.appendChild(actionViewItemElement);
this.viewItems.push(item);
this._actionIds.push(action.id);
} else {
this.actionsList.insertBefore(actionViewItemElement, this.actionsList.children[index]);
this.viewItems.splice(index, 0, item);
this._actionIds.splice(index, 0, action.id);
index++;
}
});
......@@ -317,12 +325,14 @@ export class ActionBar extends Disposable implements IActionRunner {
if (index >= 0 && index < this.viewItems.length) {
this.actionsList.removeChild(this.actionsList.childNodes[index]);
dispose(this.viewItems.splice(index, 1));
this._actionIds.splice(index, 1);
}
}
clear(): void {
dispose(this.viewItems);
this.viewItems = [];
this._actionIds = [];
DOM.clearNode(this.actionsList);
}
......@@ -463,6 +473,8 @@ export class ActionBar extends Disposable implements IActionRunner {
dispose(this.viewItems);
this.viewItems = [];
this._actionIds = [];
DOM.removeNode(this.getContainer());
super.dispose();
......
......@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
import { ActionBar, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action, Separator } from 'vs/base/common/actions';
suite('Actionbar', () => {
......@@ -24,4 +24,37 @@ suite('Actionbar', () => {
assert(actions[1] === a5);
assert(actions[2] === a6);
});
test('hasAction()', function () {
const container = document.createElement('div');
const actionbar = new ActionBar(container);
let a1 = new Action('a1');
let a2 = new Action('a2');
actionbar.push(a1);
assert.equal(actionbar.hasAction(a1), true);
assert.equal(actionbar.hasAction(a2), false);
actionbar.pull(0);
assert.equal(actionbar.hasAction(a1), false);
actionbar.push(a1, { index: 1 });
actionbar.push(a2, { index: 0 });
assert.equal(actionbar.hasAction(a1), true);
assert.equal(actionbar.hasAction(a2), true);
actionbar.pull(0);
assert.equal(actionbar.hasAction(a1), true);
assert.equal(actionbar.hasAction(a2), false);
actionbar.pull(0);
assert.equal(actionbar.hasAction(a1), false);
assert.equal(actionbar.hasAction(a2), false);
actionbar.push(a1);
assert.equal(actionbar.hasAction(a1), true);
actionbar.clear();
assert.equal(actionbar.hasAction(a1), false);
});
});
......@@ -10,7 +10,7 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups } from 'vs/workbench/browser/parts/editor/editorCommands';
import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, ActiveEditorMoveArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, mergeAllGroups, UNPIN_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands';
import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder, OpenEditorContext } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
......@@ -406,6 +406,24 @@ export class CloseEditorAction extends Action {
}
}
export class UnpinEditorAction extends Action {
static readonly ID = 'workbench.action.unpinActiveEditor';
static readonly LABEL = nls.localize('unpinEditor', "Unpin Editor");
constructor(
id: string,
label: string,
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, Codicon.pin.classNames);
}
run(context?: IEditorCommandsContext): Promise<void> {
return this.commandService.executeCommand(UNPIN_EDITOR_COMMAND_ID, undefined, context);
}
}
export class CloseOneEditorAction extends Action {
static readonly ID = 'workbench.action.closeActiveEditor';
......
......@@ -62,9 +62,9 @@
padding-left: 10px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.close-button-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.close-button-off:not(.sticky-compact) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left (unless sticky-compact) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon.tab-actions-off:not(.sticky-compact) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab actions is not left (unless sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
......@@ -123,19 +123,19 @@
position: static;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-left .action-label {
margin-right: 4px !important;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off::after {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left::after,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off::after {
content: '';
display: flex;
flex: 0;
width: 5px; /* Reserve space to hide tab fade when close button is left or off (fixes https://github.com/Microsoft/vscode/issues/45728) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-left {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left {
min-width: 80px; /* make more room for close button when it shows to the left */
padding-right: 5px; /* we need less room when sizing is shrink */
}
......@@ -148,7 +148,7 @@
pointer-events: none; /* prevents cursor flickering (fixes https://github.com/Microsoft/vscode/issues/38753) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-left {
flex-direction: row-reverse;
padding-left: 0;
padding-right: 10px;
......@@ -236,57 +236,57 @@
height: 16px; /* tweak the icon size of the editor labels when icons are enabled */
}
/* Tab Close */
/* Tab Actions */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-actions {
margin-top: auto;
margin-bottom: auto;
width: 28px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions {
flex: 0;
overflow: hidden; /* let the close button be pushed out of view when sizing is set to shrink to make more room... */
overflow: hidden; /* let the tab actions be pushed out of view when sizing is set to shrink to make more room... */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.close-button-right.sizing-shrink > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink:hover > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-right.sizing-shrink > .tab-close:focus-within {
overflow: visible; /* ...but still show the close button on hover, focus and when dirty */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty.tab-actions-right.sizing-shrink > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink:hover > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-right.sizing-shrink > .tab-actions:focus-within {
overflow: visible; /* ...but still show the tab actions on hover, focus and when dirty */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.sticky-compact > .tab-close {
display: none; /* hide the close action bar when we are configured to hide it (unless dirty, but always when sticky-compact) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off:not(.dirty) > .tab-actions,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.sticky-compact > .tab-actions {
display: none; /* hide the tab actions when we are configured to hide it (unless dirty, but always when sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-actions .action-label, /* always show tab actions for active tab */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-actions .action-label:focus, /* always show tab actions on focus */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-actions .action-label, /* always show tab actions on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-actions .action-label, /* always show tab actions on hover */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-actions .action-label { /* always show tab actions for dirty tabs */
opacity: 1;
}
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label.codicon {
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-actions .action-label.codicon {
color: inherit;
font-size: 16px;
}
/* change close icon to dirty state icon */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label:not(:hover)::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label:not(:hover)::before {
/* change tab actions icon to dirty state icon if tab dirty */
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-actions .action-label:not(:hover)::before,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label:not(:hover)::before {
content: "\ea71"; /* use `circle-filled` icon unicode */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-actions .action-label, /* show tab actions dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-actions .action-label, /* show tab actions dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label, /* show tab actions dimmed for inactive group */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-actions .action-label { /* show tab actions dimmed for inactive group */
opacity: 0.5;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-close .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab > .tab-actions .action-label {
opacity: 0;
display: block;
height: 16px;
......@@ -297,26 +297,26 @@
margin-right: 0.5em;
}
/* No Tab Close Button */
/* No Tab Actions */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off {
padding-right: 10px; /* give a little bit more room if close button is off */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off {
padding-right: 10px; /* give a little bit more room if tab actions is off */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off:not(.sticky-compact) {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-off:not(.sticky-compact) {
padding-right: 5px; /* we need less room when sizing is shrink (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty-border-top > .tab-close {
display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without close button */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty-border-top > .tab-actions {
display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without tab actions */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top):not(.sticky-compact) {
padding-right: 0; /* remove extra padding when we are running without close button (unless tab is sticky-compact) */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off.dirty:not(.dirty-border-top):not(.sticky-compact) {
padding-right: 0; /* remove extra padding when we are running without tab actions (unless tab is sticky-compact) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off > .tab-close {
pointer-events: none; /* don't allow dirty state/close button to be clicked when running without close button */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.tab-actions-off > .tab-actions {
pointer-events: none; /* don't allow tab actions to be clicked when running without tab actions */
}
/* Editor Actions */
......
......@@ -20,7 +20,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IMenuService } from 'vs/platform/actions/common/actions';
import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { getOrSet } from 'vs/base/common/map';
......@@ -35,7 +35,7 @@ import { MergeGroupMode, IMergeGroupOptions, GroupsArrangement, IEditorGroupsSer
import { addClass, addDisposableListener, hasClass, EventType, EventHelper, removeClass, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IEditorGroupsAccessor, IEditorGroupView, EditorServiceImpl, EDITOR_TITLE_HEIGHT } from 'vs/workbench/browser/parts/editor/editor';
import { CloseOneEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
import { CloseOneEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BreadcrumbsControl } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
import { IFileService } from 'vs/platform/files/common/files';
......@@ -45,6 +45,7 @@ import { basenameOrAuthority } from 'vs/base/common/resources';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { IPath, win32, posix } from 'vs/base/common/path';
import { insert } from 'vs/base/common/arrays';
interface IEditorInputLabel {
name?: string;
......@@ -74,10 +75,12 @@ export class TabsTitleControl extends TitleControl {
private editorToolbarContainer: HTMLElement | undefined;
private tabsScrollbar: ScrollableElement | undefined;
private closeOneEditorAction: CloseOneEditorAction;
private readonly closeEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL));
private readonly unpinEditorAction = this._register(this.instantiationService.createInstance(UnpinEditorAction, UnpinEditorAction.ID, UnpinEditorAction.LABEL));
private tabResourceLabels: ResourceLabels;
private readonly tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
private tabLabels: IEditorInputLabel[] = [];
private tabActionBars: ActionBar[] = [];
private tabDisposables: IDisposable[] = [];
private dimension: Dimension | undefined;
......@@ -108,9 +111,6 @@ export class TabsTitleControl extends TitleControl {
) {
super(parent, accessor, group, contextMenuService, instantiationService, contextKeyService, keybindingService, telemetryService, notificationService, menuService, quickInputService, themeService, extensionService, configurationService, fileService);
this.tabResourceLabels = this._register(this.instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER));
this.closeOneEditorAction = this._register(this.instantiationService.createInstance(CloseOneEditorAction, CloseOneEditorAction.ID, CloseOneEditorAction.LABEL));
// Resolve the correct path library for the OS we are on
// If we are connected to remote, this accounts for the
// remote OS.
......@@ -426,6 +426,7 @@ export class TabsTitleControl extends TitleControl {
this.tabDisposables = dispose(this.tabDisposables);
this.tabResourceLabels.clear();
this.tabLabels = [];
this.tabActionBars = [];
this.clearEditorActionsToolbar();
}
......@@ -439,8 +440,8 @@ export class TabsTitleControl extends TitleControl {
this.tabLabels.splice(targetIndex, 0, editorLabel);
// As such we need to redraw each tab
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel);
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar);
});
// Moving an editor requires a layout to keep the active editor visible
......@@ -462,7 +463,7 @@ export class TabsTitleControl extends TitleControl {
private doHandleStickyEditorChange(editor: IEditorInput): void {
// Update tab
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel));
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar) => this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar));
// A change to the sticky state requires a layout to keep the active editor visible
this.layout(this.dimension);
......@@ -535,23 +536,24 @@ export class TabsTitleControl extends TitleControl {
this.redraw();
}
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private forEachTab(fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar) => void): void {
this.group.editors.forEach((editor, index) => {
this.doWithTab(index, editor, fn);
});
}
private withTab(editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private withTab(editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar) => void): void {
this.doWithTab(this.group.getIndexOfEditor(editor), editor, fn);
}
private doWithTab(index: number, editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel) => void): void {
private doWithTab(index: number, editor: IEditorInput, fn: (editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar) => void): void {
const tabsContainer = assertIsDefined(this.tabsContainer);
const tabContainer = tabsContainer.children[index] as HTMLElement;
const tabResourceLabel = this.tabResourceLabels.get(index);
const tabLabel = this.tabLabels[index];
const tabActionBar = this.tabActionBars[index];
if (tabContainer && tabResourceLabel && tabLabel) {
fn(editor, index, tabContainer, tabResourceLabel, tabLabel);
fn(editor, index, tabContainer, tabResourceLabel, tabLabel, tabActionBar);
}
}
......@@ -575,26 +577,35 @@ export class TabsTitleControl extends TitleControl {
// Tab Editor Label
const editorLabel = this.tabResourceLabels.create(tabContainer);
// Tab Close Button
const tabCloseContainer = document.createElement('div');
addClass(tabCloseContainer, 'tab-close');
tabContainer.appendChild(tabCloseContainer);
// Tab Actions
const tabActionsContainer = document.createElement('div');
addClass(tabActionsContainer, 'tab-actions');
tabContainer.appendChild(tabActionsContainer);
const tabActionRunner = new EditorCommandsContextActionRunner({ groupId: this.group.id, editorIndex: index });
const tabActionBar = new ActionBar(tabActionsContainer, {
ariaLabel: localize('ariaLabelTabActions', "Tab actions"),
actionRunner: tabActionRunner,
});
tabActionBar.onDidBeforeRun(e => {
if (e.action.id === this.closeEditorAction.id) {
this.blockRevealActiveTabOnce();
}
});
const tabActionBarDisposable = combinedDisposable(tabActionBar, toDisposable(insert(this.tabActionBars, tabActionBar)));
// Tab Border Bottom
const tabBorderBottomContainer = document.createElement('div');
addClass(tabBorderBottomContainer, 'tab-border-bottom-container');
tabContainer.appendChild(tabBorderBottomContainer);
const tabActionRunner = new EditorCommandsContextActionRunner({ groupId: this.group.id, editorIndex: index });
const tabActionBar = new ActionBar(tabCloseContainer, { ariaLabel: localize('araLabelTabActions', "Tab actions"), actionRunner: tabActionRunner });
tabActionBar.push(this.closeOneEditorAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(this.closeOneEditorAction) });
tabActionBar.onDidBeforeRun(() => this.blockRevealActiveTabOnce());
// Eventing
const eventsDisposable = this.registerTabListeners(tabContainer, index, tabsContainer, tabsScrollbar);
this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBar, tabActionRunner, editorLabel));
this.tabDisposables.push(combinedDisposable(eventsDisposable, tabActionBarDisposable, tabActionRunner, editorLabel));
return tabContainer;
}
......@@ -657,7 +668,7 @@ export class TabsTitleControl extends TitleControl {
EventHelper.stop(e, true /* for https://github.com/Microsoft/vscode/issues/56715 */);
this.blockRevealActiveTabOnce();
this.closeOneEditorAction.run({ groupId: this.group.id, editorIndex: index });
this.closeEditorAction.run({ groupId: this.group.id, editorIndex: index });
}
}));
......@@ -1002,8 +1013,8 @@ export class TabsTitleControl extends TitleControl {
}
// For each tab
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel);
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar) => {
this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel, tabActionBar);
});
// Update Editor Actions Toolbar
......@@ -1013,24 +1024,32 @@ export class TabsTitleControl extends TitleControl {
this.layout(this.dimension);
}
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel, tabActionBar: ActionBar): void {
const isTabSticky = this.group.isSticky(index);
const options = this.accessor.partOptions;
// Label
this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel);
// Action
const tabAction = isTabSticky ? this.unpinEditorAction : this.closeEditorAction;
if (!tabActionBar.hasAction(tabAction)) {
if (!tabActionBar.isEmpty()) {
tabActionBar.clear();
}
tabActionBar.push(tabAction, { icon: true, label: false, keybinding: this.getKeybindingLabel(tabAction) });
}
// Borders / Outline
const borderRightColor = (this.getColor(TAB_BORDER) || this.getColor(contrastBorder));
tabContainer.style.borderRight = borderRightColor ? `1px solid ${borderRightColor}` : '';
tabContainer.style.outlineColor = this.getColor(activeContrastBorder) || '';
// Settings
const isTabSticky = this.group.isSticky(index);
const options = this.accessor.partOptions;
const tabCloseButton = isTabSticky && options.pinnedTabSizing === 'compact' ? 'off' /* treat sticky compact tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
const tabActionsVisibility = isTabSticky && options.pinnedTabSizing === 'compact' ? 'off' /* treat sticky compact tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
['off', 'left', 'right'].forEach(option => {
const domAction = tabCloseButton === option ? addClass : removeClass;
domAction(tabContainer, `close-button-${option}`);
const domAction = tabActionsVisibility === option ? addClass : removeClass;
domAction(tabContainer, `tab-actions-${option}`);
});
const tabSizing = isTabSticky && options.pinnedTabSizing === 'shrink' ? 'shrink' /* treat sticky shrink tabs as tabSizing: 'shrink' */ : options.tabSizing;
......@@ -1523,10 +1542,10 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
outline-offset: -5px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label {
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-actions .action-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-actions .action-label {
opacity: 1 !important;
}
`);
......
......@@ -73,7 +73,7 @@ registerSingleton(IAccessibilityService, NativeAccessibilityService, true);
class LinuxAccessibilityContribution implements IWorkbenchContribution {
constructor(
@IJSONEditingService jsonEditingService: IJSONEditingService,
@IAccessibilityService accessibilityService: AccessibilityService,
@IAccessibilityService accessibilityService: IAccessibilityService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
const forceRendererAccessibility = () => {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册