From a86d0e598d3e4b216c91a7278322a81df304982e Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 15 Jun 2018 17:49:18 +0200 Subject: [PATCH 01/10] add centeredViewLayout --- .../browser/ui/centered/centeredViewLayout.ts | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/vs/base/browser/ui/centered/centeredViewLayout.ts diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts new file mode 100644 index 0000000000000..26842799d7696 --- /dev/null +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -0,0 +1,45 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { SplitView, Sizing, IView, Orientation } from 'vs/base/browser/ui/splitview/splitview'; +import { $ } from 'vs/base/browser/dom'; +import { Event } from 'vs/base/common/event'; + +export class CenteredViewLayout { + + private splitView: SplitView; + readonly element: HTMLElement; + + constructor(container: HTMLElement, view: IView) { + this.element = $('.centered-view-layout'); + container.appendChild(this.element); + + this.splitView = new SplitView(this.element, { + inverseAltBehavior: true, + orientation: Orientation.HORIZONTAL + }); + const addEmptyView = () => { + this.splitView.addView({ + element: $('.'), + layout: () => undefined, + minimumSize: 20, + maximumSize: Number.POSITIVE_INFINITY, + onDidChange: Event.None + }, Sizing.Distribute); + }; + + addEmptyView(); + this.splitView.addView(view, Sizing.Distribute); + addEmptyView(); + } + + layout(size: number): void { + this.splitView.layout(size); + } + + dispose(): void { + this.splitView.dispose(); + } +} From 98e0b5b66f80fc1de94c412658ac30c23cbdb2b5 Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 15 Jun 2018 17:49:39 +0200 Subject: [PATCH 02/10] editorPart: plugin centeredViewLayout --- .../browser/parts/editor/editorPart.ts | 38 ++++++++++++++++- .../workbench/electron-browser/workbench.ts | 41 +++---------------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index bdac02ccfd833..e19bbe6bf3193 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -34,6 +34,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/ import { EditorDropTarget } from 'vs/workbench/browser/parts/editor/editorDropTarget'; import { localize } from 'vs/nls'; import { Color } from 'vs/base/common/color'; +import { CenteredViewLayout } from 'vs/base/browser/ui/centered/centeredViewLayout'; interface IEditorPartUIState { serializedGrid: ISerializedGrid; @@ -85,6 +86,8 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor private whenRestoredComplete: TValueCallback; private previousUIState: IEditorPartUIState; + private parentElement: HTMLElement; + private centeredViewLayout: CenteredViewLayout; constructor( id: string, @@ -695,11 +698,12 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor createContentArea(parent: HTMLElement): HTMLElement { // Grid control + this.parentElement = parent; this.doCreateGridControl(); // Container addClass(this.gridWidget.element, 'content'); - parent.appendChild(this.gridWidget.element); + this.parentElement.appendChild(this.gridWidget.element); // Drop support @@ -708,6 +712,29 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor return this.gridWidget.element; } + centerLayout(active: boolean): void { + if (!active && this.centeredViewLayout) { + this.parentElement.removeChild(this.centeredViewLayout.element); + this.parentElement.appendChild(this.gridWidget.element); + this.centeredViewLayout.dispose(); + this.centeredViewLayout = undefined; + } + + if (active) { + this.centeredViewLayout = new CenteredViewLayout(this.parentElement, { + element: this.gridWidget.element, + layout: size => this.gridWidget.layout(size, this.dimension ? this.dimension.height : this.gridWidget.maximumHeight), + minimumSize: this.gridWidget.minimumWidth, + maximumSize: this.gridWidget.maximumWidth, + onDidChange: Event.None + }); + } + } + + isLayoutCentered(): boolean { + return !!this.centeredViewLayout; + } + private doCreateGridControl(): void { // Grid Widget (with previous UI state) @@ -947,7 +974,11 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor // Layout Grid try { - this.gridWidget.layout(this.dimension.width, this.dimension.height); + if (this.centeredViewLayout) { + this.centeredViewLayout.layout(this.dimension.width); + } else { + this.gridWidget.layout(this.dimension.width, this.dimension.height); + } } catch (error) { this.gridError(error); } @@ -989,6 +1020,9 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor if (this.gridWidget) { this.gridWidget = dispose(this.gridWidget); } + if (this.centeredViewLayout) { + this.centeredViewLayout = dispose(this.centeredViewLayout); + } super.dispose(); } diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index eb99329ae51c4..28bdfcecd9888 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -108,7 +108,7 @@ import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService'; import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService'; -import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection, GroupOrientation } from 'vs/workbench/services/group/common/editorGroupsService'; +import { IEditorGroupsService, GroupDirection, preferredSideBySideGroupDirection } from 'vs/workbench/services/group/common/editorGroupsService'; import { EditorService } from 'vs/workbench/services/editor/browser/editorService'; import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/platform/url/electron-browser/inactiveExtensionUrlHandler'; import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService'; @@ -218,7 +218,6 @@ export class Workbench extends Disposable implements IPartService { private panelPosition: Position; private panelHidden: boolean; private zenMode: IZenMode; - private centeredEditorLayoutActive: boolean; private fontAliasing: FontAliasingOption; private hasInitialFilesToOpen: boolean; @@ -692,7 +691,7 @@ export class Workbench extends Disposable implements IPartService { // Restore Forced Editor Center Mode if (this.storageService.getBoolean(Workbench.centeredEditorLayoutActiveStorageKey, StorageScope.WORKSPACE, false)) { - this.centeredEditorLayoutActive = true; + this.centerEditorLayout(true); } const onRestored = (error?: Error): IWorkbenchStartedInfo => { @@ -846,9 +845,6 @@ export class Workbench extends Disposable implements IPartService { wasPanelVisible: false, transitionDisposeables: [] }; - - // Centered Editor Layout - this.centeredEditorLayoutActive = false; } private setPanelPositionFromStorageOrConfig() { @@ -1247,39 +1243,14 @@ export class Workbench extends Disposable implements IPartService { } isEditorLayoutCentered(): boolean { - return this.centeredEditorLayoutActive; + return this.editorPart.isLayoutCentered(); } - // TODO@ben support centered editor layout using empty groups or not? functionality missing: - // - resize sashes left and right in sync - // - IEditorInput.supportsCenteredEditorLayout() no longer supported - // - should we just allow to enter layout even if groups > 1? what does it then mean to be - // actively in centered editor layout though? centerEditorLayout(active: boolean, skipLayout?: boolean): void { - this.centeredEditorLayoutActive = active; - this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, this.centeredEditorLayoutActive, StorageScope.WORKSPACE); + this.storageService.store(Workbench.centeredEditorLayoutActiveStorageKey, active, StorageScope.WORKSPACE); // Enter Centered Editor Layout - if (active) { - if (this.editorGroupService.count === 1) { - const activeGroup = this.editorGroupService.activeGroup; - this.editorGroupService.addGroup(activeGroup, GroupDirection.LEFT); - this.editorGroupService.addGroup(activeGroup, GroupDirection.RIGHT); - - this.editorGroupService.applyLayout({ groups: [{ size: 0.2 }, { size: 0.6 }, { size: 0.2 }], orientation: GroupOrientation.HORIZONTAL }); - } - } - - // Leave Centered Editor Layout - else { - if (this.editorGroupService.count === 3) { - this.editorGroupService.groups.forEach(group => { - if (group.count === 0) { - this.editorGroupService.removeGroup(group); - } - }); - } - } + this.editorPart.centerLayout(active); if (!skipLayout) { this.layout(); @@ -1460,4 +1431,4 @@ export class Workbench extends Disposable implements IPartService { } //#endregion -} \ No newline at end of file +} From e362c61effc3ea3d01aa664b65d4ced0e595cfab Mon Sep 17 00:00:00 2001 From: isidor Date: Fri, 15 Jun 2018 18:02:01 +0200 Subject: [PATCH 03/10] update the content class name depending on who is direct chald of editor part --- src/vs/workbench/browser/parts/editor/editorPart.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index e19bbe6bf3193..951dedd8061e0 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -720,6 +720,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor this.centeredViewLayout = undefined; } + toggleClass(this.gridWidget.element, 'content', !active); if (active) { this.centeredViewLayout = new CenteredViewLayout(this.parentElement, { element: this.gridWidget.element, @@ -728,6 +729,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor maximumSize: this.gridWidget.maximumWidth, onDidChange: Event.None }); + addClass(this.centeredViewLayout.element, 'content'); } } From 151790c37d1fb3b51c2c0f1bac5977aae15af4e7 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 18 Jun 2018 11:56:16 +0200 Subject: [PATCH 04/10] center layout by adding empty views, do not reparent html elements --- .../browser/ui/centered/centeredViewLayout.ts | 35 +++++++++++++------ .../browser/parts/editor/editorPart.ts | 32 ++++++----------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 26842799d7696..6ed81c034a1f4 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -11,6 +11,7 @@ export class CenteredViewLayout { private splitView: SplitView; readonly element: HTMLElement; + private active: boolean; constructor(container: HTMLElement, view: IView) { this.element = $('.centered-view-layout'); @@ -20,25 +21,37 @@ export class CenteredViewLayout { inverseAltBehavior: true, orientation: Orientation.HORIZONTAL }); - const addEmptyView = () => { - this.splitView.addView({ - element: $('.'), - layout: () => undefined, - minimumSize: 20, - maximumSize: Number.POSITIVE_INFINITY, - onDidChange: Event.None - }, Sizing.Distribute); - }; - addEmptyView(); this.splitView.addView(view, Sizing.Distribute); - addEmptyView(); } layout(size: number): void { this.splitView.layout(size); } + isActive(): boolean { + return this.active; + } + + activate(active: boolean): void { + this.active = active; + if (this.active) { + const emptyView = { + element: $('.'), + layout: () => undefined, + minimumSize: 20, + maximumSize: Number.POSITIVE_INFINITY, + onDidChange: Event.None + }; + + this.splitView.addView(emptyView, Sizing.Distribute, 0); + this.splitView.addView(emptyView, Sizing.Distribute); + } else { + this.splitView.removeView(0); + this.splitView.removeView(1); + } + } + dispose(): void { this.splitView.dispose(); } diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 69a122f1422f4..324daa3736785 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -711,9 +711,16 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor addClass(this.container, 'content'); parent.appendChild(this.container); - // Grid control + // Grid control with center layout this.doCreateGridControl(); - this.container.appendChild(this.gridWidget.element); + this.centeredViewLayout = new CenteredViewLayout(this.container, { + element: this.gridWidget.element, + layout: size => this.gridWidget.layout(size, this.dimension ? this.dimension.height : this.gridWidget.maximumHeight), + minimumSize: this.gridWidget.minimumWidth, + maximumSize: this.gridWidget.maximumWidth, + onDidChange: Event.None + }); + addClass(this.centeredViewLayout.element, 'content'); // Drop support this._register(this.instantiationService.createInstance(EditorDropTarget, this, this.container)); @@ -722,28 +729,11 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor } centerLayout(active: boolean): void { - if (!active && this.centeredViewLayout) { - this.container.removeChild(this.centeredViewLayout.element); - this.container.appendChild(this.gridWidget.element); - this.centeredViewLayout.dispose(); - this.centeredViewLayout = undefined; - } - - toggleClass(this.gridWidget.element, 'content', !active); - if (active) { - this.centeredViewLayout = new CenteredViewLayout(this.container, { - element: this.gridWidget.element, - layout: size => this.gridWidget.layout(size, this.dimension ? this.dimension.height : this.gridWidget.maximumHeight), - minimumSize: this.gridWidget.minimumWidth, - maximumSize: this.gridWidget.maximumWidth, - onDidChange: Event.None - }); - addClass(this.centeredViewLayout.element, 'content'); - } + this.centeredViewLayout.activate(active); } isLayoutCentered(): boolean { - return !!this.centeredViewLayout; + return this.centeredViewLayout.isActive(); } private doCreateGridControl(): void { From 01bafa17275aaab1f58d3976c7a88e3e36612276 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 18 Jun 2018 12:15:17 +0200 Subject: [PATCH 05/10] centered layout: respect separator style --- src/vs/base/browser/ui/centered/centeredViewLayout.ts | 6 +++++- src/vs/workbench/browser/parts/editor/editorPart.ts | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 6ed81c034a1f4..8e520d637108a 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SplitView, Sizing, IView, Orientation } from 'vs/base/browser/ui/splitview/splitview'; +import { SplitView, Sizing, IView, Orientation, ISplitViewStyles } from 'vs/base/browser/ui/splitview/splitview'; import { $ } from 'vs/base/browser/dom'; import { Event } from 'vs/base/common/event'; @@ -33,6 +33,10 @@ export class CenteredViewLayout { return this.active; } + styles(style: ISplitViewStyles): void { + this.splitView.style(style); + } + activate(active: boolean): void { this.active = active; if (this.active) { diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 324daa3736785..111668da7eae5 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -701,7 +701,9 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor protected updateStyles(): void { this.container.style.backgroundColor = this.getColor(editorBackground); - this.gridWidget.style({ separatorBorder: this.gridSeparatorBorder }); + const separatorBorderStyle = { separatorBorder: this.gridSeparatorBorder }; + this.gridWidget.style(separatorBorderStyle); + this.centeredViewLayout.styles(separatorBorderStyle); } createContentArea(parent: HTMLElement): HTMLElement { From 899aef9c9d50bb170bff15590b8ab8bb0d4cb5d4 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 18 Jun 2018 15:25:44 +0200 Subject: [PATCH 06/10] centerd view: address feedback --- .../browser/ui/centered/centeredViewLayout.ts | 87 +++++++++++++------ .../browser/parts/editor/editorPart.ts | 36 ++++---- 2 files changed, 79 insertions(+), 44 deletions(-) diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 8e520d637108a..ea3b31ae99df7 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -3,60 +3,93 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SplitView, Sizing, IView, Orientation, ISplitViewStyles } from 'vs/base/browser/ui/splitview/splitview'; +import { SplitView, Sizing, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview'; import { $ } from 'vs/base/browser/dom'; import { Event } from 'vs/base/common/event'; +import { IView } from 'vs/base/browser/ui/grid/gridview'; export class CenteredViewLayout { private splitView: SplitView; - readonly element: HTMLElement; - private active: boolean; + private element: HTMLElement; + private height: number; + private style: ISplitViewStyles; - constructor(container: HTMLElement, view: IView) { - this.element = $('.centered-view-layout'); - container.appendChild(this.element); - - this.splitView = new SplitView(this.element, { - inverseAltBehavior: true, - orientation: Orientation.HORIZONTAL - }); - - this.splitView.addView(view, Sizing.Distribute); + constructor(private container: HTMLElement, private view: IView) { + this.container.appendChild(this.view.element); } - layout(size: number): void { - this.splitView.layout(size); + layout(width: number, height: number): void { + this.height = height; + if (this.splitView) { + this.splitView.layout(width); + } else { + this.view.layout(width, height); + } } isActive(): boolean { - return this.active; + return !!this.splitView; } styles(style: ISplitViewStyles): void { - this.splitView.style(style); + this.style = style; + if (this.splitView) { + this.splitView.style(this.style); + } + } + + resetView(view: IView): void { + this.view = view; + if (this.splitView) { + this.splitView.removeView(1); + this.splitView.addView(this.getView(), Sizing.Distribute, 1); + } + } + + private getView(): ISplitViewView { + return { + element: this.view.element, + maximumSize: this.view.maximumWidth, + minimumSize: this.view.minimumWidth, + onDidChange: Event.None, + layout: size => this.view.layout(size, this.height) + }; } activate(active: boolean): void { - this.active = active; - if (this.active) { - const emptyView = { - element: $('.'), + if (active) { + this.element = $('.centered-view-layout'); + this.container.removeChild(this.view.element); + this.container.appendChild(this.element); + this.splitView = new SplitView(this.element, { + inverseAltBehavior: true, + orientation: Orientation.HORIZONTAL, + styles: this.style + }); + + const getEmptyView = () => ({ + element: $('.centered-layout-margin'), layout: () => undefined, minimumSize: 20, maximumSize: Number.POSITIVE_INFINITY, onDidChange: Event.None - }; + }); - this.splitView.addView(emptyView, Sizing.Distribute, 0); - this.splitView.addView(emptyView, Sizing.Distribute); + this.splitView.addView(getEmptyView(), Sizing.Distribute); + this.splitView.addView(this.getView(), Sizing.Distribute); + this.splitView.addView(getEmptyView(), Sizing.Distribute); } else { - this.splitView.removeView(0); - this.splitView.removeView(1); + this.splitView.dispose(); + this.splitView = undefined; + this.container.removeChild(this.element); + this.container.appendChild(this.view.element); } } dispose(): void { - this.splitView.dispose(); + if (this.splitView) { + this.splitView.dispose(); + } } } diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index 111668da7eae5..e3e0891aa1f23 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -35,6 +35,7 @@ import { EditorDropTarget } from 'vs/workbench/browser/parts/editor/editorDropTa import { localize } from 'vs/nls'; import { Color } from 'vs/base/common/color'; import { CenteredViewLayout } from 'vs/base/browser/ui/centered/centeredViewLayout'; +import { IView } from 'vs/base/browser/ui/grid/gridview'; interface IEditorPartUIState { serializedGrid: ISerializedGrid; @@ -715,14 +716,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor // Grid control with center layout this.doCreateGridControl(); - this.centeredViewLayout = new CenteredViewLayout(this.container, { - element: this.gridWidget.element, - layout: size => this.gridWidget.layout(size, this.dimension ? this.dimension.height : this.gridWidget.maximumHeight), - minimumSize: this.gridWidget.minimumWidth, - maximumSize: this.gridWidget.maximumWidth, - onDidChange: Event.None - }); - addClass(this.centeredViewLayout.element, 'content'); + this.centeredViewLayout = new CenteredViewLayout(this.container, this.getGridAsView()); // Drop support this._register(this.instantiationService.createInstance(EditorDropTarget, this, this.container)); @@ -730,6 +724,18 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor return this.container; } + private getGridAsView(): IView { + return { + element: this.gridWidget.element, + layout: (width, height) => this.gridWidget.layout(width, height), + minimumWidth: this.gridWidget.minimumWidth, + maximumWidth: this.gridWidget.maximumWidth, + minimumHeight: this.gridWidget.minimumHeight, + maximumHeight: this.gridWidget.minimumHeight, + onDidChange: Event.None + }; + } + centerLayout(active: boolean): void { this.centeredViewLayout.activate(active); } @@ -829,7 +835,9 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor this.gridWidget = gridWidget; if (gridWidget) { - this.container.appendChild(gridWidget.element); + if (this.centeredViewLayout) { + this.centeredViewLayout.resetView(this.getGridAsView()); + } this._onDidSizeConstraintsChange.input = gridWidget.onDidChange; } @@ -987,11 +995,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor // Layout Grid try { - if (this.centeredViewLayout) { - this.centeredViewLayout.layout(this.dimension.width); - } else { - this.gridWidget.layout(this.dimension.width, this.dimension.height); - } + this.centeredViewLayout.layout(this.dimension.width, this.dimension.height); } catch (error) { this.gridError(error); } @@ -1033,9 +1037,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor if (this.gridWidget) { this.gridWidget.dispose(); } - if (this.centeredViewLayout) { - this.centeredViewLayout = dispose(this.centeredViewLayout); - } + this.centeredViewLayout.dispose(); super.dispose(); } From 2370f863fa87e96ee211083b3d7f3f52bcaae0ab Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 18 Jun 2018 15:43:27 +0200 Subject: [PATCH 07/10] properly pass onDidChange and react to other feedback --- src/vs/base/browser/ui/centered/centeredViewLayout.ts | 9 +++++++-- src/vs/workbench/browser/parts/editor/editorPart.ts | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index ea3b31ae99df7..418a6973aad9f 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -5,7 +5,7 @@ import { SplitView, Sizing, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview'; import { $ } from 'vs/base/browser/dom'; -import { Event } from 'vs/base/common/event'; +import { Event, mapEvent } from 'vs/base/common/event'; import { IView } from 'vs/base/browser/ui/grid/gridview'; export class CenteredViewLayout { @@ -44,6 +44,7 @@ export class CenteredViewLayout { if (this.splitView) { this.splitView.removeView(1); this.splitView.addView(this.getView(), Sizing.Distribute, 1); + this.splitView.distributeViewSizes(); } } @@ -52,12 +53,16 @@ export class CenteredViewLayout { element: this.view.element, maximumSize: this.view.maximumWidth, minimumSize: this.view.minimumWidth, - onDidChange: Event.None, + onDidChange: mapEvent(this.view.onDidChange, ({ width }) => width), layout: size => this.view.layout(size, this.height) }; } activate(active: boolean): void { + if (active === !!this.splitView) { + return; + } + if (active) { this.element = $('.centered-view-layout'); this.container.removeChild(this.view.element); diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index e3e0891aa1f23..f43f1221db3df 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -732,7 +732,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor maximumWidth: this.gridWidget.maximumWidth, minimumHeight: this.gridWidget.minimumHeight, maximumHeight: this.gridWidget.minimumHeight, - onDidChange: Event.None + onDidChange: this.gridWidget.onDidChange }; } From 8f7a6420fd8a21f327878f8d6a3b3dbdeb499773 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 18 Jun 2018 16:10:25 +0200 Subject: [PATCH 08/10] use helper functino to clarify toSplitViewView cast --- .../browser/ui/centered/centeredViewLayout.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 418a6973aad9f..664cb9d3e6d66 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -8,6 +8,16 @@ import { $ } from 'vs/base/browser/dom'; import { Event, mapEvent } from 'vs/base/common/event'; import { IView } from 'vs/base/browser/ui/grid/gridview'; +function toSplitViewView(view: IView, getHeight: () => number): ISplitViewView { + return { + element: view.element, + maximumSize: view.maximumWidth, + minimumSize: view.minimumWidth, + onDidChange: mapEvent(view.onDidChange, widthAndHeight => widthAndHeight ? widthAndHeight.width : 0), + layout: size => view.layout(size, getHeight()) + }; +} + export class CenteredViewLayout { private splitView: SplitView; @@ -43,21 +53,11 @@ export class CenteredViewLayout { this.view = view; if (this.splitView) { this.splitView.removeView(1); - this.splitView.addView(this.getView(), Sizing.Distribute, 1); + this.splitView.addView(toSplitViewView(this.view, () => this.height), Sizing.Distribute, 1); this.splitView.distributeViewSizes(); } } - private getView(): ISplitViewView { - return { - element: this.view.element, - maximumSize: this.view.maximumWidth, - minimumSize: this.view.minimumWidth, - onDidChange: mapEvent(this.view.onDidChange, ({ width }) => width), - layout: size => this.view.layout(size, this.height) - }; - } - activate(active: boolean): void { if (active === !!this.splitView) { return; @@ -82,7 +82,7 @@ export class CenteredViewLayout { }); this.splitView.addView(getEmptyView(), Sizing.Distribute); - this.splitView.addView(this.getView(), Sizing.Distribute); + this.splitView.addView(toSplitViewView(this.view, () => this.height), Sizing.Distribute); this.splitView.addView(getEmptyView(), Sizing.Distribute); } else { this.splitView.dispose(); From 4d2c0dd0b9f7a1e33a001a10f1d7842af9bc2981 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 18 Jun 2018 16:45:43 +0200 Subject: [PATCH 09/10] centeredViewLayout: height 100% to show watermark --- src/vs/base/browser/ui/centered/centeredViewLayout.css | 8 ++++++++ src/vs/base/browser/ui/centered/centeredViewLayout.ts | 2 ++ 2 files changed, 10 insertions(+) create mode 100644 src/vs/base/browser/ui/centered/centeredViewLayout.css diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.css b/src/vs/base/browser/ui/centered/centeredViewLayout.css new file mode 100644 index 0000000000000..854530732a0bb --- /dev/null +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.css @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +.monaco-workbench > .part.editor > .content .centered-view-layout { + height: 100%; +} diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 664cb9d3e6d66..1e3a40e319b63 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import 'vs/css!./centeredViewLayout'; + import { SplitView, Sizing, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview'; import { $ } from 'vs/base/browser/dom'; import { Event, mapEvent } from 'vs/base/common/event'; From 8527801364f831933850162ad2fa70b565514c36 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 19 Jun 2018 10:51:04 +0200 Subject: [PATCH 10/10] centeredView: store ratios and restore them properly --- .../browser/ui/centered/centeredViewLayout.ts | 50 +++++++++++++++---- .../browser/parts/editor/editorPart.ts | 7 ++- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/vs/base/browser/ui/centered/centeredViewLayout.ts b/src/vs/base/browser/ui/centered/centeredViewLayout.ts index 1e3a40e319b63..c3c97743d8b38 100644 --- a/src/vs/base/browser/ui/centered/centeredViewLayout.ts +++ b/src/vs/base/browser/ui/centered/centeredViewLayout.ts @@ -5,39 +5,59 @@ import 'vs/css!./centeredViewLayout'; -import { SplitView, Sizing, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview'; +import { SplitView, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview'; import { $ } from 'vs/base/browser/dom'; -import { Event, mapEvent } from 'vs/base/common/event'; +import { Event, mapEvent, anyEvent } from 'vs/base/common/event'; import { IView } from 'vs/base/browser/ui/grid/gridview'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; function toSplitViewView(view: IView, getHeight: () => number): ISplitViewView { return { element: view.element, maximumSize: view.maximumWidth, minimumSize: view.minimumWidth, - onDidChange: mapEvent(view.onDidChange, widthAndHeight => widthAndHeight ? widthAndHeight.width : 0), + onDidChange: mapEvent(view.onDidChange, widthAndHeight => widthAndHeight && widthAndHeight.width), layout: size => view.layout(size, getHeight()) }; } +export interface CenteredViewState { + leftMarginRatio: number; + rightMarginRatio: number; +} + +const GOLDEN_RATIO = { + leftMarginRatio: 0.1909, + rightMarginRatio: 0.1909 +}; + export class CenteredViewLayout { private splitView: SplitView; private element: HTMLElement; - private height: number; + private width: number = 0; + private height: number = 0; private style: ISplitViewStyles; + private didLayout = false; + private splitViewDisposable: IDisposable[] = []; - constructor(private container: HTMLElement, private view: IView) { + constructor(private container: HTMLElement, private view: IView, public readonly state: CenteredViewState = GOLDEN_RATIO) { this.container.appendChild(this.view.element); } layout(width: number, height: number): void { + this.width = width; this.height = height; if (this.splitView) { this.splitView.layout(width); + if (!this.didLayout) { + this.splitView.resizeView(0, this.state.leftMarginRatio * this.width); + this.splitView.resizeView(2, this.state.rightMarginRatio * this.width); + } } else { this.view.layout(width, height); } + this.didLayout = true; } isActive(): boolean { @@ -54,8 +74,9 @@ export class CenteredViewLayout { resetView(view: IView): void { this.view = view; if (this.splitView) { + const size = this.splitView.getViewSize(1); this.splitView.removeView(1); - this.splitView.addView(toSplitViewView(this.view, () => this.height), Sizing.Distribute, 1); + this.splitView.addView(toSplitViewView(this.view, () => this.height), size, 1); this.splitView.distributeViewSizes(); } } @@ -75,18 +96,27 @@ export class CenteredViewLayout { styles: this.style }); + const onDidSizesChange = anyEvent(this.splitView.onDidSashChange, this.splitView.onDidSashReset); + this.splitViewDisposable.push(onDidSizesChange(() => { + this.state.leftMarginRatio = this.splitView.getViewSize(0) / this.width; + this.state.rightMarginRatio = this.splitView.getViewSize(2) / this.width; + })); + + this.splitView.layout(this.width); + const getEmptyView = () => ({ element: $('.centered-layout-margin'), layout: () => undefined, - minimumSize: 20, + minimumSize: 40, maximumSize: Number.POSITIVE_INFINITY, onDidChange: Event.None }); - this.splitView.addView(getEmptyView(), Sizing.Distribute); - this.splitView.addView(toSplitViewView(this.view, () => this.height), Sizing.Distribute); - this.splitView.addView(getEmptyView(), Sizing.Distribute); + this.splitView.addView(toSplitViewView(this.view, () => this.height), 0); + this.splitView.addView(getEmptyView(), this.state.leftMarginRatio * this.width, 0); + this.splitView.addView(getEmptyView(), this.state.rightMarginRatio * this.width, 2); } else { + this.splitViewDisposable = dispose(this.splitViewDisposable); this.splitView.dispose(); this.splitView = undefined; this.container.removeChild(this.element); diff --git a/src/vs/workbench/browser/parts/editor/editorPart.ts b/src/vs/workbench/browser/parts/editor/editorPart.ts index f43f1221db3df..53be612944931 100644 --- a/src/vs/workbench/browser/parts/editor/editorPart.ts +++ b/src/vs/workbench/browser/parts/editor/editorPart.ts @@ -48,6 +48,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor _serviceBrand: any; private static readonly EDITOR_PART_UI_STATE_STORAGE_KEY = 'editorpart.state'; + private static readonly EDITOR_PART_CENTERED_VIEW_STORAGE_KEY = 'editorpart.centeredview'; //#region Events @@ -79,6 +80,8 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor private _preferredSize: Dimension; private memento: object; + private globalMemento: object; + private _partOptions: IEditorPartOptions; private _activeGroup: IEditorGroupView; @@ -109,6 +112,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor this._partOptions = getEditorPartOptions(this.configurationService.getValue()); this.memento = this.getMemento(this.storageService, Scope.WORKSPACE); + this.globalMemento = this.getMemento(this.storageService, Scope.GLOBAL); this._whenRestored = new TPromise(resolve => { this.whenRestoredComplete = resolve; @@ -716,7 +720,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor // Grid control with center layout this.doCreateGridControl(); - this.centeredViewLayout = new CenteredViewLayout(this.container, this.getGridAsView()); + this.centeredViewLayout = new CenteredViewLayout(this.container, this.getGridAsView(), this.globalMemento[EditorPart.EDITOR_PART_CENTERED_VIEW_STORAGE_KEY]); // Drop support this._register(this.instantiationService.createInstance(EditorDropTarget, this, this.container)); @@ -1020,6 +1024,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor this.memento[EditorPart.EDITOR_PART_UI_STATE_STORAGE_KEY] = uiState; } } + this.globalMemento[EditorPart.EDITOR_PART_CENTERED_VIEW_STORAGE_KEY] = this.centeredViewLayout.state; // Forward to all groups this.groupViews.forEach(group => group.shutdown());