mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
debt - introduce editorTitleControl as container for tabs/notabs
This commit is contained in:
@@ -118,7 +118,7 @@ export interface IEditorGroupTitleHeight {
|
||||
/**
|
||||
* The height offset to e.g. use when drawing drop overlays.
|
||||
* This number may be smaller than `height` if the title control
|
||||
* decides to have an `offset` that is within the title area
|
||||
* decides to have an `offset` that is within the title control
|
||||
* (e.g. when breadcrumbs are enabled).
|
||||
*/
|
||||
offset: number;
|
||||
|
||||
@@ -11,7 +11,7 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
|
||||
import { Emitter, Relay } from 'vs/base/common/event';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, IDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, isAncestor, IDomNodePagePosition } from 'vs/base/browser/dom';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
@@ -19,7 +19,6 @@ import { IThemeService, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { editorBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND, EDITOR_GROUP_EMPTY_BACKGROUND, EDITOR_GROUP_HEADER_BORDER } from 'vs/workbench/common/theme';
|
||||
import { ICloseEditorsFilter, GroupsOrder, ICloseEditorOptions, ICloseAllEditorsOptions, IEditorReplacement } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { MultiEditorTabsControl } from 'vs/workbench/browser/parts/editor/multiEditorTabsControl';
|
||||
import { EditorPanes } from 'vs/workbench/browser/parts/editor/editorPanes';
|
||||
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { EditorProgressIndicator } from 'vs/workbench/services/progress/browser/progressIndicator';
|
||||
@@ -29,12 +28,10 @@ import { MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DeferredPromise, Promises, RunOnceWorker } from 'vs/base/common/async';
|
||||
import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { EditorTabsControl } from 'vs/workbench/browser/parts/editor/editorTabsControl';
|
||||
import { IEditorGroupsAccessor, IEditorGroupView, fillActiveEditorViewState, EditorServiceImpl, IEditorGroupTitleHeight, IInternalEditorOpenOptions, IInternalMoveCopyOptions, IInternalEditorCloseOptions, IInternalEditorTitleControlOptions } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { SingleEditorTabsControl } from 'vs/workbench/browser/parts/editor/singleEditorTabsControl';
|
||||
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
@@ -55,6 +52,7 @@ import { TelemetryTrustedValue } from 'vs/platform/telemetry/common/telemetryUti
|
||||
import { defaultProgressBarStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
|
||||
import { EditorGroupWatermark } from 'vs/workbench/browser/parts/editor/editorGroupWatermark';
|
||||
import { EditorTitleControl } from 'vs/workbench/browser/parts/editor/editorTitleControl';
|
||||
|
||||
export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
@@ -118,7 +116,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
private readonly scopedInstantiationService: IInstantiationService;
|
||||
|
||||
private readonly titleContainer: HTMLElement;
|
||||
private titleAreaControl: EditorTabsControl;
|
||||
private readonly titleControl: EditorTitleControl;
|
||||
|
||||
private readonly progressBar: ProgressBar;
|
||||
|
||||
@@ -200,7 +198,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.element.appendChild(this.titleContainer);
|
||||
|
||||
// Title control
|
||||
this.titleAreaControl = this.createTitleAreaControl();
|
||||
this.titleControl = this._register(this.scopedInstantiationService.createInstance(EditorTitleControl, this.titleContainer, this.accessor, this));
|
||||
|
||||
// Editor container
|
||||
this.editorContainer = document.createElement('div');
|
||||
@@ -458,24 +456,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.titleContainer.classList.toggle('show-file-icons', this.accessor.partOptions.showIcons);
|
||||
}
|
||||
|
||||
private createTitleAreaControl(): EditorTabsControl {
|
||||
|
||||
// Clear old if existing
|
||||
if (this.titleAreaControl) {
|
||||
this.titleAreaControl.dispose();
|
||||
clearNode(this.titleContainer);
|
||||
}
|
||||
|
||||
// Create new based on options
|
||||
if (this.accessor.partOptions.showTabs) {
|
||||
this.titleAreaControl = this.scopedInstantiationService.createInstance(MultiEditorTabsControl, this.titleContainer, this.accessor, this);
|
||||
} else {
|
||||
this.titleAreaControl = this.scopedInstantiationService.createInstance(SingleEditorTabsControl, this.titleContainer, this.accessor, this);
|
||||
}
|
||||
|
||||
return this.titleAreaControl;
|
||||
}
|
||||
|
||||
private restoreEditors(from: IEditorGroupView | ISerializedEditorGroupModel | null): Promise<void> | undefined {
|
||||
if (this.count === 0) {
|
||||
return; // nothing to show
|
||||
@@ -702,26 +682,21 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Title container
|
||||
this.updateTitleContainer();
|
||||
|
||||
// Title control
|
||||
this.titleControl.updateOptions(event.oldPartOptions, event.newPartOptions);
|
||||
|
||||
// Title control Switch between showing tabs <=> not showing tabs
|
||||
if (event.oldPartOptions.showTabs !== event.newPartOptions.showTabs) {
|
||||
|
||||
// Recreate title control
|
||||
this.createTitleAreaControl();
|
||||
|
||||
// Re-layout
|
||||
this.relayout();
|
||||
|
||||
// Ensure to show active editor if any
|
||||
if (this.model.activeEditor) {
|
||||
this.titleAreaControl.openEditor(this.model.activeEditor);
|
||||
this.titleControl.openEditor(this.model.activeEditor);
|
||||
}
|
||||
}
|
||||
|
||||
// Just update title control
|
||||
else {
|
||||
this.titleAreaControl.updateOptions(event.oldPartOptions, event.newPartOptions);
|
||||
}
|
||||
|
||||
// Styles
|
||||
this.updateStyles();
|
||||
|
||||
@@ -739,13 +714,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.pinEditor(editor);
|
||||
|
||||
// Forward to title control
|
||||
this.titleAreaControl.updateEditorDirty(editor);
|
||||
this.titleControl.updateEditorDirty(editor);
|
||||
}
|
||||
|
||||
private onDidChangeEditorLabel(editor: EditorInput): void {
|
||||
|
||||
// Forward to title control
|
||||
this.titleAreaControl.updateEditorLabel(editor);
|
||||
this.titleControl.updateEditorLabel(editor);
|
||||
}
|
||||
|
||||
private onDidVisibilityChange(visible: boolean): void {
|
||||
@@ -780,7 +755,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
get titleHeight(): IEditorGroupTitleHeight {
|
||||
return this.titleAreaControl.getHeight();
|
||||
return this.titleControl.getHeight();
|
||||
}
|
||||
|
||||
notifyIndexChanged(newIndex: number): void {
|
||||
@@ -798,7 +773,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.element.classList.toggle('inactive', !isActive);
|
||||
|
||||
// Update title control
|
||||
this.titleAreaControl.setActive(isActive);
|
||||
this.titleControl.setActive(isActive);
|
||||
|
||||
// Update styles
|
||||
this.updateStyles();
|
||||
@@ -925,7 +900,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Forward to title control
|
||||
if (editor) {
|
||||
this.titleAreaControl.pinEditor(editor);
|
||||
this.titleControl.pinEditor(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -952,14 +927,14 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// title control and also make sure to emit this as an event
|
||||
const newIndexOfEditor = this.getIndexOfEditor(editor);
|
||||
if (newIndexOfEditor !== oldIndexOfEditor) {
|
||||
this.titleAreaControl.moveEditor(editor, oldIndexOfEditor, newIndexOfEditor);
|
||||
this.titleControl.moveEditor(editor, oldIndexOfEditor, newIndexOfEditor);
|
||||
}
|
||||
|
||||
// Forward sticky state to title control
|
||||
if (sticky) {
|
||||
this.titleAreaControl.stickEditor(editor);
|
||||
this.titleControl.stickEditor(editor);
|
||||
} else {
|
||||
this.titleAreaControl.unstickEditor(editor);
|
||||
this.titleControl.unstickEditor(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1119,7 +1094,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Show in title control after editor control because some actions depend on it
|
||||
// but respect the internal options in case title control updates should skip.
|
||||
if (!internalOptions?.skipTitleUpdate) {
|
||||
this.titleAreaControl.openEditor(editor);
|
||||
this.titleControl.openEditor(editor);
|
||||
}
|
||||
|
||||
return openEditorPromise;
|
||||
@@ -1169,7 +1144,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}));
|
||||
|
||||
// Update the title control all at once with all editors
|
||||
this.titleAreaControl.openEditors(inactiveEditors.map(({ editor }) => editor));
|
||||
this.titleControl.openEditors(inactiveEditors.map(({ editor }) => editor));
|
||||
|
||||
// Opening many editors at once can put any editor to be
|
||||
// the active one depending on options. As such, we simply
|
||||
@@ -1200,8 +1175,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// in source and target if the title update was skipped
|
||||
if (internalOptions.skipTitleUpdate) {
|
||||
const movedEditors = editors.map(({ editor }) => editor);
|
||||
target.titleAreaControl.openEditors(movedEditors);
|
||||
this.titleAreaControl.closeEditors(movedEditors);
|
||||
target.titleControl.openEditors(movedEditors);
|
||||
this.titleControl.closeEditors(movedEditors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1241,9 +1216,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.model.moveEditor(editor, moveToIndex);
|
||||
this.model.pin(editor);
|
||||
|
||||
// Forward to title area
|
||||
this.titleAreaControl.moveEditor(editor, currentIndex, moveToIndex);
|
||||
this.titleAreaControl.pinEditor(editor);
|
||||
// Forward to title control
|
||||
this.titleControl.moveEditor(editor, currentIndex, moveToIndex);
|
||||
this.titleControl.pinEditor(editor);
|
||||
}
|
||||
|
||||
private doMoveOrCopyEditorAcrossGroups(editor: EditorInput, target: EditorGroupView, openOptions?: IEditorOpenOptions, internalOptions?: IInternalMoveCopyOptions): void {
|
||||
@@ -1299,7 +1274,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// in target if the title update was skipped
|
||||
if (internalOptions.skipTitleUpdate) {
|
||||
const copiedEditors = editors.map(({ editor }) => editor);
|
||||
target.titleAreaControl.openEditors(copiedEditors);
|
||||
target.titleControl.openEditors(copiedEditors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1346,7 +1321,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Forward to title control unless skipped via internal options
|
||||
if (!internalOptions?.skipTitleUpdate) {
|
||||
this.titleAreaControl.beforeCloseEditor(editor);
|
||||
this.titleControl.beforeCloseEditor(editor);
|
||||
}
|
||||
|
||||
// Closing the active editor of the group is a bit more work
|
||||
@@ -1361,7 +1336,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Forward to title control unless skipped via internal options
|
||||
if (!internalOptions?.skipTitleUpdate) {
|
||||
this.titleAreaControl.closeEditor(editor);
|
||||
this.titleControl.closeEditor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1711,7 +1686,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Forward to title control
|
||||
if (editors.length) {
|
||||
this.titleAreaControl.closeEditors(editors);
|
||||
this.titleControl.closeEditors(editors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1763,7 +1738,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// Forward to title control
|
||||
if (editorsToClose.length) {
|
||||
this.titleAreaControl.closeEditors(editorsToClose);
|
||||
this.titleControl.closeEditors(editorsToClose);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1922,16 +1897,16 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.lastLayout = { width, height, top, left };
|
||||
this.element.classList.toggle('max-height-478px', height <= 478);
|
||||
|
||||
// Layout the title area first to receive the size it occupies
|
||||
const titleAreaSize = this.titleAreaControl.layout({
|
||||
// Layout the title control first to receive the size it occupies
|
||||
const titleControlSize = this.titleControl.layout({
|
||||
container: new Dimension(width, height),
|
||||
available: new Dimension(width, height - this.editorPane.minimumHeight)
|
||||
});
|
||||
|
||||
// Pass the container width and remaining height to the editor layout
|
||||
const editorHeight = Math.max(0, height - titleAreaSize.height);
|
||||
const editorHeight = Math.max(0, height - titleControlSize.height);
|
||||
this.editorContainer.style.height = `${editorHeight}px`;
|
||||
this.editorPane.layout({ width, height: editorHeight, top: top + titleAreaSize.height, left });
|
||||
this.editorPane.layout({ width, height: editorHeight, top: top + titleControlSize.height, left });
|
||||
}
|
||||
|
||||
relayout(): void {
|
||||
@@ -1956,8 +1931,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
this._onWillDispose.fire();
|
||||
|
||||
this.titleAreaControl.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Dimension, clearNode } from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IThemeService, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { IEditorGroupsAccessor, IEditorGroupTitleHeight, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { EditorTabsControl, IEditorTabsControlDimensions } from 'vs/workbench/browser/parts/editor/editorTabsControl';
|
||||
import { MultiEditorTabsControl } from 'vs/workbench/browser/parts/editor/multiEditorTabsControl';
|
||||
import { SingleEditorTabsControl } from 'vs/workbench/browser/parts/editor/singleEditorTabsControl';
|
||||
import { IEditorPartOptions } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
|
||||
export class EditorTitleControl extends Themable {
|
||||
|
||||
private editorTabsControl: EditorTabsControl;
|
||||
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
private accessor: IEditorGroupsAccessor,
|
||||
private group: IEditorGroupView,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
this.editorTabsControl = this.createEditorTabsControl();
|
||||
}
|
||||
|
||||
private createEditorTabsControl(): EditorTabsControl {
|
||||
if (this.accessor.partOptions.showTabs) {
|
||||
return this.instantiationService.createInstance(MultiEditorTabsControl, this.parent, this.accessor, this.group);
|
||||
}
|
||||
|
||||
return this.instantiationService.createInstance(SingleEditorTabsControl, this.parent, this.accessor, this.group);
|
||||
}
|
||||
|
||||
openEditor(editor: EditorInput): void {
|
||||
return this.editorTabsControl.openEditor(editor);
|
||||
}
|
||||
|
||||
openEditors(editors: EditorInput[]): void {
|
||||
return this.editorTabsControl.openEditors(editors);
|
||||
}
|
||||
|
||||
beforeCloseEditor(editor: EditorInput): void {
|
||||
return this.editorTabsControl.beforeCloseEditor(editor);
|
||||
}
|
||||
|
||||
closeEditor(editor: EditorInput): void {
|
||||
return this.editorTabsControl.closeEditor(editor);
|
||||
}
|
||||
|
||||
closeEditors(editors: EditorInput[]): void {
|
||||
return this.editorTabsControl.closeEditors(editors);
|
||||
}
|
||||
|
||||
moveEditor(editor: EditorInput, fromIndex: number, targetIndex: number): void {
|
||||
return this.editorTabsControl.moveEditor(editor, fromIndex, targetIndex);
|
||||
}
|
||||
|
||||
pinEditor(editor: EditorInput): void {
|
||||
return this.editorTabsControl.pinEditor(editor);
|
||||
}
|
||||
|
||||
stickEditor(editor: EditorInput): void {
|
||||
return this.editorTabsControl.stickEditor(editor);
|
||||
}
|
||||
|
||||
unstickEditor(editor: EditorInput): void {
|
||||
return this.editorTabsControl.unstickEditor(editor);
|
||||
}
|
||||
|
||||
setActive(isActive: boolean): void {
|
||||
return this.editorTabsControl.setActive(isActive);
|
||||
}
|
||||
|
||||
updateEditorLabel(editor: EditorInput): void {
|
||||
return this.editorTabsControl.updateEditorLabel(editor);
|
||||
}
|
||||
|
||||
updateEditorDirty(editor: EditorInput): void {
|
||||
return this.editorTabsControl.updateEditorDirty(editor);
|
||||
}
|
||||
|
||||
updateOptions(oldOptions: IEditorPartOptions, newOptions: IEditorPartOptions): void {
|
||||
|
||||
// Update editor tabs control if options changed
|
||||
if (oldOptions.showTabs !== newOptions.showTabs) {
|
||||
|
||||
// Clear old
|
||||
this.editorTabsControl.dispose();
|
||||
clearNode(this.parent);
|
||||
|
||||
// Create new
|
||||
this.editorTabsControl = this.createEditorTabsControl();
|
||||
}
|
||||
|
||||
// Forward into editor tabs control
|
||||
this.editorTabsControl.updateOptions(oldOptions, newOptions);
|
||||
}
|
||||
|
||||
layout(dimensions: IEditorTabsControlDimensions): Dimension {
|
||||
return this.editorTabsControl.layout(dimensions);
|
||||
}
|
||||
|
||||
getHeight(): IEditorGroupTitleHeight {
|
||||
return this.editorTabsControl.getHeight();
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
this.editorTabsControl.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1089,7 +1089,7 @@ export class MultiEditorTabsControl extends EditorTabsControl {
|
||||
if (Array.isArray(data)) {
|
||||
const group = data[0];
|
||||
if (group.identifier === this.group.id) {
|
||||
return false; // groups cannot be dropped on title area it originates from
|
||||
return false; // groups cannot be dropped on group it originates from
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user