未验证 提交 6a1ca400 编写于 作者: I Isidor Nikolic 提交者: GitHub

Merge pull request #52064 from Microsoft/isidorn/centeredLayout

Centered editor layout
/*---------------------------------------------------------------------------------------------
* 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%;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./centeredViewLayout';
import { SplitView, Orientation, ISplitViewStyles, IView as ISplitViewView } from 'vs/base/browser/ui/splitview/splitview';
import { $ } from 'vs/base/browser/dom';
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),
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 width: number = 0;
private height: number = 0;
private style: ISplitViewStyles;
private didLayout = false;
private splitViewDisposable: IDisposable[] = [];
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 {
return !!this.splitView;
}
styles(style: ISplitViewStyles): void {
this.style = style;
if (this.splitView) {
this.splitView.style(this.style);
}
}
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), size, 1);
this.splitView.distributeViewSizes();
}
}
activate(active: boolean): void {
if (active === !!this.splitView) {
return;
}
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 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: 40,
maximumSize: Number.POSITIVE_INFINITY,
onDidChange: Event.None
});
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);
this.container.appendChild(this.view.element);
}
}
dispose(): void {
if (this.splitView) {
this.splitView.dispose();
}
}
}
......@@ -34,6 +34,8 @@ 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';
import { IView } from 'vs/base/browser/ui/grid/gridview';
interface IEditorPartUIState {
serializedGrid: ISerializedGrid;
......@@ -46,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
......@@ -77,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;
......@@ -90,6 +95,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
private whenRestoredComplete: TValueCallback<void>;
private previousUIState: IEditorPartUIState;
private centeredViewLayout: CenteredViewLayout;
constructor(
id: string,
......@@ -106,6 +112,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
this._partOptions = getEditorPartOptions(this.configurationService.getValue<IWorkbenchEditorConfiguration>());
this.memento = this.getMemento(this.storageService, Scope.WORKSPACE);
this.globalMemento = this.getMemento(this.storageService, Scope.GLOBAL);
this._whenRestored = new TPromise(resolve => {
this.whenRestoredComplete = resolve;
......@@ -699,7 +706,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 {
......@@ -709,8 +718,9 @@ 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.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));
......@@ -718,6 +728,26 @@ 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: this.gridWidget.onDidChange
};
}
centerLayout(active: boolean): void {
this.centeredViewLayout.activate(active);
}
isLayoutCentered(): boolean {
return this.centeredViewLayout.isActive();
}
private doCreateGridControl(): void {
// Grid Widget (with previous UI state)
......@@ -809,7 +839,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;
}
......@@ -967,7 +999,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
// Layout Grid
try {
this.gridWidget.layout(this.dimension.width, this.dimension.height);
this.centeredViewLayout.layout(this.dimension.width, this.dimension.height);
} catch (error) {
this.gridError(error);
}
......@@ -992,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());
......@@ -1009,6 +1042,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
if (this.gridWidget) {
this.gridWidget.dispose();
}
this.centeredViewLayout.dispose();
super.dispose();
}
......
......@@ -110,7 +110,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 { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
......@@ -227,7 +227,6 @@ export class Workbench extends Disposable implements IPartService {
private panelHidden: boolean;
private menubarHidden: boolean;
private zenMode: IZenMode;
private centeredEditorLayoutActive: boolean;
private fontAliasing: FontAliasingOption;
private hasInitialFilesToOpen: boolean;
......@@ -714,7 +713,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 => {
......@@ -872,9 +871,6 @@ export class Workbench extends Disposable implements IPartService {
wasPanelVisible: false,
transitionDisposeables: []
};
// Centered Editor Layout
this.centeredEditorLayoutActive = false;
}
private setPanelPositionFromStorageOrConfig() {
......@@ -1293,39 +1289,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();
......@@ -1514,4 +1485,4 @@ export class Workbench extends Disposable implements IPartService {
}
//#endregion
}
\ No newline at end of file
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册