未验证 提交 777c8e57 编写于 作者: J João Moreno 提交者: GitHub

Merge pull request #51989 from Microsoft/joao/grid-constraing-propagation

Workbench grid dimension constraint propagation
......@@ -10,6 +10,7 @@ import { Orientation } from 'vs/base/browser/ui/sash/sash';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { tail2 as tail } from 'vs/base/common/arrays';
import { orthogonal, IView, GridView, Sizing as GridViewSizing, Box, IGridViewStyles } from './gridview';
import { Event } from 'vs/base/common/event';
export { Orientation } from './gridview';
......@@ -192,9 +193,9 @@ export class Grid<T extends IView> implements IDisposable {
get minimumWidth(): number { return this.gridview.minimumWidth; }
get minimumHeight(): number { return this.gridview.minimumHeight; }
get maximumWidth(): number { return this.gridview.maximumWidth; }
get maximumHeight(): number { return this.gridview.maximumHeight; }
get onDidChange(): Event<{ width: number; height: number; }> { return this.gridview.onDidChange; }
get element(): HTMLElement { return this.gridview.element; }
......
......@@ -104,11 +104,11 @@ class BranchNode implements ISplitView, IDisposable {
}
get minimumOrthogonalSize(): number {
return this.children.length === 0 ? 0 : this.children.reduce((r, c) => r + c.minimumSize, 0);
return this.splitview.minimumSize;
}
get maximumOrthogonalSize(): number {
return this.children.length === 0 ? Number.POSITIVE_INFINITY : this.children.reduce((r, c) => r + c.maximumSize, 0);
return this.splitview.maximumSize;
}
get minimumWidth(): number {
......@@ -363,7 +363,7 @@ class LeafNode implements ISplitView, IDisposable {
}
get onDidChange(): Event<number> {
return mapEvent(this.view.onDidChange, this.orientation === Orientation.HORIZONTAL ? ({ width }) => width : ({ height }) => height);
return mapEvent(this.view.onDidChange, this.orientation === Orientation.HORIZONTAL ? e => e && e.width : e => e && e.height);
}
set orthogonalStartSash(sash: Sash) {
......@@ -442,6 +442,7 @@ export class GridView implements IDisposable {
this._root = root;
this.element.appendChild(root.element);
this.onDidSashResetRelay.input = root.onDidSashReset;
this._onDidChange.input = mapEvent(root.onDidChange, () => undefined); // TODO
}
get orientation(): Orientation {
......@@ -459,29 +460,16 @@ export class GridView implements IDisposable {
this.root.orthogonalLayout(orthogonalSize);
}
get width(): number {
return this.root.width;
}
get height(): number {
return this.root.height;
}
get width(): number { return this.root.width; }
get height(): number { return this.root.height; }
get minimumWidth(): number {
return this.root.minimumWidth;
}
get minimumWidth(): number { return this.root.minimumWidth; }
get minimumHeight(): number { return this.root.minimumHeight; }
get maximumWidth(): number { return this.root.maximumHeight; }
get maximumHeight(): number { return this.root.maximumHeight; }
get minimumHeight(): number {
return this.root.minimumHeight;
}
get maximumWidth(): number {
return this.root.maximumHeight;
}
get maximumHeight(): number {
return this.root.maximumHeight;
}
private _onDidChange = new Relay<{ width: number; height: number; }>();
readonly onDidChange = this._onDidChange.event;
constructor(options: IGridViewOptions = {}) {
this.element = $('.monaco-grid-view');
......
......@@ -148,6 +148,14 @@ export class SplitView implements IDisposable {
return this.viewItems.length;
}
get minimumSize(): number {
return this.viewItems.reduce((r, item) => r + item.view.minimumSize, 0);
}
get maximumSize(): number {
return this.length === 0 ? Number.POSITIVE_INFINITY : this.viewItems.reduce((r, item) => r + item.view.maximumSize, 0);
}
private _orthogonalStartSash: Sash | undefined;
get orthogonalStartSash(): Sash | undefined { return this._orthogonalStartSash; }
set orthogonalStartSash(sash: Sash | undefined) {
......
......@@ -117,23 +117,23 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
private registerListeners(): void {
this._register(this.themeService.onThemeChange(_ => this.layout()));
this._register(this.parts.editor.onDidPreferredSizeChange(() => this.onDidPreferredSizeChange()));
this._register(this.parts.editor.onDidSizeConstraintsChange(() => this.onDidEditorSizeConstraintsChange()));
this.registerSashListeners();
}
private onDidPreferredSizeChange(): void {
private onDidEditorSizeConstraintsChange(): void {
if (this.workbenchSize && (this.sidebarWidth || this.panelHeight)) {
if (this.editorGroupService.count > 1) {
const preferredEditorPartSize = this.parts.editor.preferredSize;
const minimumEditorPartSize = new Dimension(this.parts.editor.minimumWidth, this.parts.editor.minimumHeight);
const sidebarOverflow = this.workbenchSize.width - this.sidebarWidth < preferredEditorPartSize.width;
const sidebarOverflow = this.workbenchSize.width - this.sidebarWidth < minimumEditorPartSize.width;
let panelOverflow = false;
if (this.partService.getPanelPosition() === Position.RIGHT) {
panelOverflow = this.workbenchSize.width - this.panelWidth - this.sidebarWidth < preferredEditorPartSize.width;
panelOverflow = this.workbenchSize.width - this.panelWidth - this.sidebarWidth < minimumEditorPartSize.width;
} else {
panelOverflow = this.workbenchSize.height - this.panelHeight < preferredEditorPartSize.height;
panelOverflow = this.workbenchSize.height - this.panelHeight < minimumEditorPartSize.height;
}
// Trigger a layout if we detect that either sidebar or panel overflow
......@@ -191,11 +191,11 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
minSidebarWidth = 0;
}
return Math.max(this.partLayoutInfo.panel.minWidth, this.workbenchSize.width - this.parts.editor.preferredSize.width - minSidebarWidth - this.activitybarWidth);
return Math.max(this.partLayoutInfo.panel.minWidth, this.workbenchSize.width - this.parts.editor.minimumWidth - minSidebarWidth - this.activitybarWidth);
}
private computeMaxPanelHeight(): number {
return Math.max(this.partLayoutInfo.panel.minHeight, this.sidebarHeight /* simplification for: window.height - status.height - title-height */ - this.parts.editor.preferredSize.height);
return Math.max(this.partLayoutInfo.panel.minHeight, this.sidebarHeight /* simplification for: window.height - status.height - title-height */ - this.parts.editor.minimumHeight);
}
private get sidebarWidth(): number {
......@@ -208,7 +208,7 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
private set sidebarWidth(value: number) {
const panelMinWidth = this.partService.getPanelPosition() === Position.RIGHT && this.partService.isVisible(Parts.PANEL_PART) ? this.partLayoutInfo.panel.minWidth : 0;
const maxSidebarWidth = this.workbenchSize.width - this.activitybarWidth - this.parts.editor.preferredSize.width - panelMinWidth;
const maxSidebarWidth = this.workbenchSize.width - this.activitybarWidth - this.parts.editor.minimumWidth - panelMinWidth;
this._sidebarWidth = Math.max(this.partLayoutInfo.sidebar.minWidth, Math.min(maxSidebarWidth, value));
}
......@@ -486,10 +486,10 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
editorSize.width = this.workbenchSize.width - sidebarSize.width - activityBarSize.width - (panelPosition === Position.RIGHT ? panelDimension.width : 0);
editorSize.height = sidebarSize.height - (panelPosition === Position.BOTTOM ? panelDimension.height : 0);
// Adjust for Editor Part preferred width
const preferredEditorPartSize = this.parts.editor.preferredSize;
if (editorSize.width < preferredEditorPartSize.width) {
const missingPreferredEditorWidth = preferredEditorPartSize.width - editorSize.width;
// Adjust for Editor Part minimum width
const minimumEditorPartSize = new Dimension(this.parts.editor.minimumWidth, this.parts.editor.minimumHeight);
if (editorSize.width < minimumEditorPartSize.width) {
const missingPreferredEditorWidth = minimumEditorPartSize.width - editorSize.width;
let outstandingMissingPreferredEditorWidth = missingPreferredEditorWidth;
// Take from Panel if Panel Position on the Right and Visible
......@@ -512,9 +512,9 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
}
}
// Adjust for Editor Part preferred height
if (editorSize.height < preferredEditorPartSize.height) {
const missingPreferredEditorHeight = preferredEditorPartSize.height - editorSize.height;
// Adjust for Editor Part minimum height
if (editorSize.height < minimumEditorPartSize.height) {
const missingPreferredEditorHeight = minimumEditorPartSize.height - editorSize.height;
let outstandingMissingPreferredEditorHeight = missingPreferredEditorHeight;
// Take from Panel if Panel Position on the Bottom and Visible
......@@ -713,9 +713,8 @@ export class WorkbenchLayout extends Disposable implements IVerticalSashLayoutPr
case Parts.SIDEBAR_PART:
this.sidebarWidth = this.sidebarWidth + sizeChangePxWidth; // Sidebar can not become smaller than MIN_PART_WIDTH
const preferredEditorPartSize = this.parts.editor.preferredSize;
if (this.workbenchSize.width - this.sidebarWidth < preferredEditorPartSize.width) {
this.sidebarWidth = this.workbenchSize.width - preferredEditorPartSize.width;
if (this.workbenchSize.width - this.sidebarWidth < this.parts.editor.minimumWidth) {
this.sidebarWidth = this.workbenchSize.width - this.parts.editor.minimumWidth;
}
doLayout = true;
......
......@@ -14,8 +14,9 @@ import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/group/
import { IStorageService } from 'vs/platform/storage/common/storage';
import { LRUCache } from 'vs/base/common/map';
import URI from 'vs/base/common/uri';
import { once } from 'vs/base/common/event';
import { once, Event } from 'vs/base/common/event';
import { isEmptyObject } from 'vs/base/common/types';
import { DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor';
/**
* The base class of editors in the workbench. Editors register themselves for specific editor inputs.
......@@ -32,6 +33,13 @@ import { isEmptyObject } from 'vs/base/common/types';
*/
export abstract class BaseEditor extends Panel implements IEditor {
readonly minimumWidth = DEFAULT_EDITOR_MIN_DIMENSIONS.width;
readonly maximumWidth = DEFAULT_EDITOR_MAX_DIMENSIONS.width;
readonly minimumHeight = DEFAULT_EDITOR_MIN_DIMENSIONS.height;
readonly maximumHeight = DEFAULT_EDITOR_MAX_DIMENSIONS.height;
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = Event.None;
private static readonly EDITOR_MEMENTOS: Map<string, EditorMemento<any>> = new Map<string, EditorMemento<any>>();
protected _input: EditorInput;
......
......@@ -21,8 +21,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
export const EDITOR_TITLE_HEIGHT = 35;
export const EDITOR_MIN_DIMENSIONS = new Dimension(220, 70);
export const EDITOR_MAX_DIMENSIONS = new Dimension(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
export const DEFAULT_EDITOR_MIN_DIMENSIONS = new Dimension(220, 70);
export const DEFAULT_EDITOR_MAX_DIMENSIONS = new Dimension(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
export interface IEditorPartOptions extends IWorkbenchEditorPartConfiguration {
iconTheme?: string;
......
......@@ -16,7 +16,7 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgressService, LongRunningOperation } from 'vs/platform/progress/common/progress';
import { toWinJsPromise } from 'vs/base/common/async';
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { IEditorGroupView, DEFAULT_EDITOR_MIN_DIMENSIONS, DEFAULT_EDITOR_MAX_DIMENSIONS } from 'vs/workbench/browser/parts/editor/editor';
import { Event, Emitter } from 'vs/base/common/event';
export interface IOpenEditorResult {
......@@ -26,17 +26,24 @@ export interface IOpenEditorResult {
export class EditorControl extends Disposable {
get minimumWidth() { return this._activeControl ? this._activeControl.minimumWidth : DEFAULT_EDITOR_MIN_DIMENSIONS.width; }
get minimumHeight() { return this._activeControl ? this._activeControl.minimumHeight : DEFAULT_EDITOR_MIN_DIMENSIONS.height; }
get maximumWidth() { return this._activeControl ? this._activeControl.maximumWidth : DEFAULT_EDITOR_MAX_DIMENSIONS.width; }
get maximumHeight() { return this._activeControl ? this._activeControl.maximumHeight : DEFAULT_EDITOR_MAX_DIMENSIONS.height; }
private _onDidFocus: Emitter<void> = this._register(new Emitter<void>());
get onDidFocus(): Event<void> { return this._onDidFocus.event; }
private activeControlFocusListener: IDisposable;
private dimension: Dimension;
private editorOperation: LongRunningOperation;
private _onDidSizeConstraintsChange = this._register(new Emitter<{ width: number; height: number; }>());
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return this._onDidSizeConstraintsChange.event; }
private _activeControl: BaseEditor;
private controls: BaseEditor[] = [];
private activeControlDisposeables: IDisposable[] = [];
private dimension: Dimension;
private editorOperation: LongRunningOperation;
constructor(
private parent: HTMLElement,
private groupView: IEditorGroupView,
......@@ -76,16 +83,13 @@ export class EditorControl extends Disposable {
// Create editor
const control = this.doCreateEditorControl(descriptor);
// Remember editor as active
this._activeControl = control;
// Set editor as active
this.doSetActiveControl(control);
// Show editor
this.parent.appendChild(control.getContainer());
show(control.getContainer());
// Track focus
this.activeControlFocusListener = control.onDidFocus(() => this._onDidFocus.fire());
// Indicate to editor that it is now visible
control.setVisible(true, this.groupView);
......@@ -129,6 +133,22 @@ export class EditorControl extends Disposable {
return control;
}
private doSetActiveControl(control: BaseEditor) {
this._activeControl = control;
// Clear out previous active control listeners
this.activeControlDisposeables = dispose(this.activeControlDisposeables);
// Listen to control changes
if (control) {
this.activeControlDisposeables.push(control.onDidSizeConstraintsChange(e => this._onDidSizeConstraintsChange.fire(e)));
this.activeControlDisposeables.push(control.onDidFocus(() => this._onDidFocus.fire()));
}
// Indicate that size constraints could have changed due to new editor
this._onDidSizeConstraintsChange.fire();
}
private doSetInput(control: BaseEditor, editor: EditorInput, options: EditorOptions): TPromise<boolean> {
// If the input did not change, return early and only apply the options
......@@ -196,10 +216,7 @@ export class EditorControl extends Disposable {
this._activeControl.setVisible(false, this.groupView);
// Clear active control
this._activeControl = null;
// Clear focus listener
this.activeControlFocusListener = dispose(this.activeControlFocusListener);
this.doSetActiveControl(null);
}
closeEditor(editor: EditorInput): void {
......@@ -223,7 +240,7 @@ export class EditorControl extends Disposable {
}
dispose(): void {
this.activeControlFocusListener = dispose(this.activeControlFocusListener);
this.activeControlDisposeables = dispose(this.activeControlDisposeables);
super.dispose();
}
......
......@@ -9,7 +9,7 @@ import 'vs/css!./media/editorgroupview';
import { TPromise } from 'vs/base/common/winjs.base';
import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup';
import { EditorInput, EditorOptions, GroupIdentifier, ConfirmResult, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext } from 'vs/workbench/common/editor';
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter, once, Relay } from 'vs/base/common/event';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
......@@ -34,7 +34,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { RunOnceWorker } from 'vs/base/common/async';
import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
import { TitleControl } from 'vs/workbench/browser/parts/editor/titleControl';
import { IEditorGroupsAccessor, IEditorGroupView, IEditorPartOptionsChangeEvent, EDITOR_TITLE_HEIGHT, EDITOR_MIN_DIMENSIONS, EDITOR_MAX_DIMENSIONS, getActiveTextEditorOptions, IEditorOpeningEvent } from 'vs/workbench/browser/parts/editor/editor';
import { IEditorGroupsAccessor, IEditorGroupView, IEditorPartOptionsChangeEvent, EDITOR_TITLE_HEIGHT, getActiveTextEditorOptions, IEditorOpeningEvent } from 'vs/workbench/browser/parts/editor/editor';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { join } from 'vs/base/common/paths';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
......@@ -197,6 +197,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Editor control
this.editorControl = this._register(this.scopedInstantiationService.createInstance(EditorControl, this.editorContainer, this));
this._onDidChange.input = this.editorControl.onDidSizeConstraintsChange;
// Track Focus
this.doTrackFocus();
......@@ -1330,12 +1331,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
readonly element: HTMLElement = document.createElement('div');
readonly minimumWidth = EDITOR_MIN_DIMENSIONS.width;
readonly minimumHeight = EDITOR_MIN_DIMENSIONS.height;
readonly maximumWidth = EDITOR_MAX_DIMENSIONS.width;
readonly maximumHeight = EDITOR_MAX_DIMENSIONS.height;
get minimumWidth(): number { return this.editorControl.minimumWidth; }
get minimumHeight(): number { return this.editorControl.minimumHeight; }
get maximumWidth(): number { return this.editorControl.maximumWidth; }
get maximumHeight(): number { return this.editorControl.maximumHeight; }
get onDidChange() { return Event.None; } // only needed if minimum sizes ever change
private _onDidChange = this._register(new Relay<{ width: number; height: number; }>());
readonly onDidChange: Event<{ width: number; height: number; }> = this._onDidChange.event;
layout(width: number, height: number): void {
this.dimension = new Dimension(width, height);
......
......@@ -9,7 +9,7 @@ import 'vs/workbench/browser/parts/editor/editor.contribution';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { Part } from 'vs/workbench/browser/part';
import { Dimension, isAncestor, toggleClass, addClass, clearNode } from 'vs/base/browser/dom';
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter, once, Relay, anyEvent } from 'vs/base/common/event';
import { contrastBorder, editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { GroupDirection, IAddGroupOptions, GroupsArrangement, GroupOrientation, IMergeGroupOptions, MergeGroupMode, ICopyEditorOptions, GroupsOrder, GroupChangeKind, GroupLocation, IFindGroupScope, EditorGroupLayout, GroupLayoutArgument } from 'vs/workbench/services/group/common/editorGroupsService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -64,6 +64,10 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
private _onDidMoveGroup: Emitter<IEditorGroupView> = this._register(new Emitter<IEditorGroupView>());
get onDidMoveGroup(): Event<IEditorGroupView> { return this._onDidMoveGroup.event; }
private onDidSetGridWidget = this._register(new Emitter<{ width: number; height: number; }>());
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
get onDidSizeConstraintsChange(): Event<{ width: number; height: number; }> { return anyEvent(this.onDidSetGridWidget.event, this._onDidSizeConstraintsChange.event); }
private _onDidPreferredSizeChange: Emitter<void> = this._register(new Emitter<void>());
get onDidPreferredSizeChange(): Event<void> { return this._onDidPreferredSizeChange.event; }
......@@ -665,6 +669,11 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
//#region Part
get minimumWidth(): number { return this.gridWidget ? this.gridWidget.minimumWidth : 0; }
get maximumWidth(): number { return this.gridWidget ? this.gridWidget.maximumWidth : Number.POSITIVE_INFINITY; }
get minimumHeight(): number { return this.gridWidget ? this.gridWidget.minimumHeight : 0; }
get maximumHeight(): number { return this.gridWidget ? this.gridWidget.maximumHeight : Number.POSITIVE_INFINITY; }
get preferredSize(): Dimension {
if (!this._preferredSize) {
this._preferredSize = new Dimension(this.gridWidget.minimumWidth, this.gridWidget.minimumHeight);
......@@ -718,7 +727,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
// Grid Widget (no previous UI state or failed to restore)
if (!this.gridWidget) {
const initialGroup = this.doCreateGroupView();
this.gridWidget = new SerializableGrid(initialGroup);
this.doSetGridWidget(new SerializableGrid(initialGroup));
// Ensure a group is active
this.doSetGroupActive(initialGroup);
......@@ -749,7 +758,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
if (this.gridWidget) {
clearNode(this.gridWidget.element);
this.gridWidget.dispose();
this.gridWidget = void 0;
this.doSetGridWidget();
}
this.groupViews.forEach(group => group.dispose());
......@@ -778,7 +787,7 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
}
// Create new
this.gridWidget = SerializableGrid.deserialize(serializedGrid, {
this.doSetGridWidget(SerializableGrid.deserialize(serializedGrid, {
fromJSON: (serializedEditorGroup: ISerializedEditorGroup) => {
let groupView: IEditorGroupView;
if (reuseGroupViews.length > 0) {
......@@ -793,7 +802,17 @@ export class EditorPart extends Part implements EditorGroupsServiceImpl, IEditor
return groupView;
}
}, { styles: { separatorBorder: this.gridSeparatorBorder } });
}, { styles: { separatorBorder: this.gridSeparatorBorder } }));
}
private doSetGridWidget(gridWidget?: SerializableGrid<IEditorGroupView>): void {
this.gridWidget = gridWidget;
if (gridWidget) {
this._onDidSizeConstraintsChange.input = gridWidget.onDidChange;
}
this.onDidSetGridWidget.fire();
}
private doGetPreviousState(): IEditorPartUIState {
......
......@@ -16,13 +16,32 @@ import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/br
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/splitview';
import { Event } from 'vs/base/common/event';
import { Event, Relay, anyEvent, mapEvent, Emitter } from 'vs/base/common/event';
export class SideBySideEditor extends BaseEditor {
public static readonly ID: string = 'workbench.editor.sidebysideEditor';
static readonly ID: string = 'workbench.editor.sidebysideEditor';
private dimension: DOM.Dimension = new DOM.Dimension(0, 0);
get minimumMasterWidth() { return this.masterEditor ? this.masterEditor.minimumWidth : 0; }
get maximumMasterWidth() { return this.masterEditor ? this.masterEditor.maximumWidth : Number.POSITIVE_INFINITY; }
get minimumMasterHeight() { return this.masterEditor ? this.masterEditor.minimumHeight : 0; }
get maximumMasterHeight() { return this.masterEditor ? this.masterEditor.maximumHeight : Number.POSITIVE_INFINITY; }
get minimumDetailsWidth() { return this.detailsEditor ? this.detailsEditor.minimumWidth : 0; }
get maximumDetailsWidth() { return this.detailsEditor ? this.detailsEditor.maximumWidth : Number.POSITIVE_INFINITY; }
get minimumDetailsHeight() { return this.detailsEditor ? this.detailsEditor.minimumHeight : 0; }
get maximumDetailsHeight() { return this.detailsEditor ? this.detailsEditor.maximumHeight : Number.POSITIVE_INFINITY; }
// these setters need to exist because this extends from BaseEditor
set minimumWidth(value: number) { /* noop */ }
set maximumWidth(value: number) { /* noop */ }
set minimumHeight(value: number) { /* noop */ }
set maximumHeight(value: number) { /* noop */ }
get minimumWidth() { return this.minimumMasterWidth + this.minimumDetailsWidth; }
get maximumWidth() { return this.maximumMasterWidth + this.maximumDetailsWidth; }
get minimumHeight() { return this.minimumMasterHeight + this.minimumDetailsHeight; }
get maximumHeight() { return this.maximumMasterHeight + this.maximumDetailsHeight; }
protected masterEditor: BaseEditor;
private masterEditorContainer: HTMLElement;
......@@ -31,6 +50,11 @@ export class SideBySideEditor extends BaseEditor {
private detailsEditorContainer: HTMLElement;
private splitview: SplitView;
private dimension: DOM.Dimension = new DOM.Dimension(0, 0);
private onDidCreateEditors = this._register(new Emitter<{ width: number; height: number; }>());
private _onDidSizeConstraintsChange = this._register(new Relay<{ width: number; height: number; }>());
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = anyEvent(this.onDidCreateEditors.event, this._onDidSizeConstraintsChange.event);
constructor(
@ITelemetryService telemetryService: ITelemetryService,
......@@ -50,7 +74,7 @@ export class SideBySideEditor extends BaseEditor {
this.detailsEditorContainer = DOM.$('.details-editor-container');
this.splitview.addView({
element: this.detailsEditorContainer,
layout: size => this.detailsEditor && this.detailsEditor.layout(new DOM.Dimension(size, this.dimension.height - 34 /* height of header container */)),
layout: size => this.detailsEditor && this.detailsEditor.layout(new DOM.Dimension(size, this.dimension.height)),
minimumSize: 220,
maximumSize: Number.POSITIVE_INFINITY,
onDidChange: Event.None
......@@ -59,7 +83,7 @@ export class SideBySideEditor extends BaseEditor {
this.masterEditorContainer = DOM.$('.master-editor-container');
this.splitview.addView({
element: this.masterEditorContainer,
layout: size => this.masterEditor && this.masterEditor.layout(new DOM.Dimension(size, this.dimension.height - 34 /* height of header container */)),
layout: size => this.masterEditor && this.masterEditor.layout(new DOM.Dimension(size, this.dimension.height)),
minimumSize: 220,
maximumSize: Number.POSITIVE_INFINITY,
onDidChange: Event.None
......@@ -68,13 +92,13 @@ export class SideBySideEditor extends BaseEditor {
this.updateStyles();
}
public setInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
setInput(newInput: SideBySideEditorInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
const oldInput = <SideBySideEditorInput>this.input;
return super.setInput(newInput, options, token)
.then(() => this.updateInput(oldInput, newInput, options, token));
}
public setOptions(options: EditorOptions): void {
setOptions(options: EditorOptions): void {
if (this.masterEditor) {
this.masterEditor.setOptions(options);
}
......@@ -90,7 +114,7 @@ export class SideBySideEditor extends BaseEditor {
super.setEditorVisible(visible, group);
}
public clearInput(): void {
clearInput(): void {
if (this.masterEditor) {
this.masterEditor.clearInput();
}
......@@ -101,33 +125,33 @@ export class SideBySideEditor extends BaseEditor {
super.clearInput();
}
public focus(): void {
focus(): void {
if (this.masterEditor) {
this.masterEditor.focus();
}
}
public layout(dimension: DOM.Dimension): void {
layout(dimension: DOM.Dimension): void {
this.dimension = dimension;
this.splitview.layout(dimension.width);
}
public getControl(): IEditorControl {
getControl(): IEditorControl {
if (this.masterEditor) {
return this.masterEditor.getControl();
}
return null;
}
public getMasterEditor(): IEditor {
getMasterEditor(): IEditor {
return this.masterEditor;
}
public getDetailsEditor(): IEditor {
getDetailsEditor(): IEditor {
return this.detailsEditor;
}
public supportsCenteredLayout(): boolean {
supportsCenteredLayout(): boolean {
return false;
}
......@@ -163,10 +187,18 @@ export class SideBySideEditor extends BaseEditor {
private onEditorsCreated(details: BaseEditor, master: BaseEditor, detailsInput: EditorInput, masterInput: EditorInput, options: EditorOptions, token: CancellationToken): TPromise<void> {
this.detailsEditor = details;
this.masterEditor = master;
this._onDidSizeConstraintsChange.input = anyEvent(
mapEvent(details.onDidSizeConstraintsChange, () => undefined),
mapEvent(master.onDidSizeConstraintsChange, () => undefined)
);
this.onDidCreateEditors.fire();
return TPromise.join([this.detailsEditor.setInput(detailsInput, null, token), this.masterEditor.setInput(masterInput, options, token)]).then(() => this.focus());
}
public updateStyles(): void {
updateStyles(): void {
super.updateStyles();
if (this.masterEditorContainer) {
......@@ -179,16 +211,19 @@ export class SideBySideEditor extends BaseEditor {
this.detailsEditor.dispose();
this.detailsEditor = null;
}
if (this.masterEditor) {
this.masterEditor.dispose();
this.masterEditor = null;
}
this.detailsEditorContainer.innerHTML = '';
this.masterEditorContainer.innerHTML = '';
}
public dispose(): void {
dispose(): void {
this.disposeEditors();
super.dispose();
}
}
......@@ -58,6 +58,31 @@ export interface IEditor {
*/
group: IEditorGroup;
/**
* The minimum width of this editor.
*/
readonly minimumWidth: number;
/**
* The maximum width of this editor.
*/
readonly maximumWidth: number;
/**
* The minimum height of this editor.
*/
readonly minimumHeight: number;
/**
* The maximum height of this editor.
*/
readonly maximumHeight: number;
/**
* An event to notify whenever minimum/maximum width/height changes.
*/
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }>;
/**
* Returns the unique identifier of this editor.
*/
......
......@@ -75,6 +75,16 @@ export class PreferencesEditor extends BaseEditor {
private lastFocusedWidget: SearchWidget | SideBySidePreferencesWidget = null;
get minimumWidth(): number { return this.sideBySidePreferencesWidget ? this.sideBySidePreferencesWidget.minimumWidth : 0; }
get maximumWidth(): number { return this.sideBySidePreferencesWidget ? this.sideBySidePreferencesWidget.maximumWidth : Number.POSITIVE_INFINITY; }
// these setters need to exist because this extends from BaseEditor
set minimumWidth(value: number) { /*noop*/ }
set maximumWidth(value: number) { /*noop*/ }
private _onDidCreateWidget = new Emitter<{ width: number; height: number; }>();
readonly onDidSizeConstraintsChange: Event<{ width: number; height: number; }> = this._onDidCreateWidget.event;
constructor(
@IPreferencesService private preferencesService: IPreferencesService,
@ITelemetryService telemetryService: ITelemetryService,
......@@ -122,6 +132,7 @@ export class PreferencesEditor extends BaseEditor {
const editorsContainer = DOM.append(parent, DOM.$('.preferences-editors-container'));
this.sideBySidePreferencesWidget = this._register(this.instantiationService.createInstance(SideBySidePreferencesWidget, editorsContainer));
this._onDidCreateWidget.fire();
this._register(this.sideBySidePreferencesWidget.onFocus(() => this.lastFocusedWidget = this.sideBySidePreferencesWidget));
this._register(this.sideBySidePreferencesWidget.onDidSettingsTargetChange(target => this.switchSettings(target)));
......@@ -326,6 +337,11 @@ export class PreferencesEditor extends BaseEditor {
this._lastReportedFilter = filter;
}
}
dispose(): void {
this._onDidCreateWidget.dispose();
super.dispose();
}
}
class SettingsNavigator extends ArrayNavigator<ISetting> {
......@@ -755,6 +771,9 @@ class SideBySidePreferencesWidget extends Widget {
private lastFocusedEditor: BaseEditor;
private splitview: SplitView;
get minimumWidth(): number { return this.splitview.minimumSize; }
get maximumWidth(): number { return this.splitview.maximumSize; }
constructor(
parentElement: HTMLElement,
@IInstantiationService private instantiationService: IInstantiationService,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册