diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 95eafa2d323..4341aa730d0 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -20,15 +20,18 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService'; import { getZoomFactor } from 'vs/base/browser/browser'; -const DEFAULT_MIN_SIDEBAR_PART_WIDTH = 170; -const DEFAULT_MIN_PANEL_PART_HEIGHT = 77; -const DEFAULT_MIN_EDITOR_PART_HEIGHT = 70; -const DEFAULT_MIN_EDITOR_PART_WIDTH = 220; +const MIN_SIDEBAR_PART_WIDTH = 170; +const MIN_EDITOR_PART_HEIGHT = 70; +const MIN_EDITOR_PART_WIDTH = 220; +const MIN_PANEL_PART_HEIGHT = 77; const DEFAULT_PANEL_HEIGHT_COEFFICIENT = 0.4; const HIDE_SIDEBAR_WIDTH_THRESHOLD = 50; const HIDE_PANEL_HEIGHT_THRESHOLD = 50; +const TITLE_BAR_HEIGHT = 22; +const STATUS_BAR_HEIGHT = 22; +const ACTIVITY_BAR_WIDTH = 50; -interface ComputedStyles { +interface PartLayoutInfo { titlebar: { height: number; }; activitybar: { width: number; }; sidebar: { minWidth: number; }; @@ -55,8 +58,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal private statusbar: Part; private quickopen: QuickOpenController; private toUnbind: IDisposable[]; - private computedStyles: ComputedStyles; - private initialComputedStyles: ComputedStyles; + private partLayoutInfo: PartLayoutInfo; private workbenchSize: Dimension; private sashX: Sash; private sashY: Sash; @@ -103,7 +105,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.statusbar = parts.statusbar; this.quickopen = quickopen; this.toUnbind = []; - this.computedStyles = null; + this.partLayoutInfo = this.getPartLayoutInfo(); this.panelHeightBeforeMaximized = 0; this.sashX = new Sash(this.workbenchContainer.getHTMLElement(), this, { @@ -120,13 +122,37 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.layoutEditorGroupsVertically = (this.editorGroupService.getGroupOrientation() !== 'horizontal'); - this.toUnbind.push(themeService.onDidColorThemeChange(_ => this.relayout())); + this.toUnbind.push(themeService.onDidColorThemeChange(_ => this.layout())); this.toUnbind.push(editorGroupService.onEditorsChanged(() => this.onEditorsChanged())); this.toUnbind.push(editorGroupService.onGroupOrientationChanged(e => this.onGroupOrientationChanged())); this.registerSashListeners(); } + private getPartLayoutInfo(): PartLayoutInfo { + return { + titlebar: { + height: TITLE_BAR_HEIGHT + }, + activitybar: { + width: ACTIVITY_BAR_WIDTH + }, + sidebar: { + minWidth: MIN_SIDEBAR_PART_WIDTH + }, + panel: { + minHeight: MIN_PANEL_PART_HEIGHT + }, + editor: { + minWidth: MIN_EDITOR_PART_WIDTH, + minHeight: MIN_EDITOR_PART_HEIGHT + }, + statusbar: { + height: STATUS_BAR_HEIGHT + } + }; + } + private registerSashListeners(): void { let startX: number = 0; let startY: number = 0; @@ -152,8 +178,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal if (isSidebarVisible) { // Automatically hide side bar when a certain threshold is met - if (newSashWidth + HIDE_SIDEBAR_WIDTH_THRESHOLD < this.computedStyles.sidebar.minWidth) { - let dragCompensation = DEFAULT_MIN_SIDEBAR_PART_WIDTH - HIDE_SIDEBAR_WIDTH_THRESHOLD; + if (newSashWidth + HIDE_SIDEBAR_WIDTH_THRESHOLD < this.partLayoutInfo.sidebar.minWidth) { + let dragCompensation = MIN_SIDEBAR_PART_WIDTH - HIDE_SIDEBAR_WIDTH_THRESHOLD; promise = this.partService.setSideBarHidden(true); startX = (sidebarPosition === Position.LEFT) ? Math.max(this.activitybarWidth, e.currentX - dragCompensation) : Math.min(e.currentX + dragCompensation, this.workbenchSize.width - this.activitybarWidth); this.sidebarWidth = this.startSidebarWidth; // when restoring sidebar, restore to the sidebar width we started from @@ -161,17 +187,17 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal // Otherwise size the sidebar accordingly else { - this.sidebarWidth = Math.max(this.computedStyles.sidebar.minWidth, newSashWidth); // Sidebar can not become smaller than MIN_PART_WIDTH - doLayout = newSashWidth >= this.computedStyles.sidebar.minWidth; + this.sidebarWidth = Math.max(this.partLayoutInfo.sidebar.minWidth, newSashWidth); // Sidebar can not become smaller than MIN_PART_WIDTH + doLayout = newSashWidth >= this.partLayoutInfo.sidebar.minWidth; } } // Sidebar hidden else { - if ((sidebarPosition === Position.LEFT && e.currentX - startX >= this.computedStyles.sidebar.minWidth) || - (sidebarPosition === Position.RIGHT && startX - e.currentX >= this.computedStyles.sidebar.minWidth)) { - this.startSidebarWidth = this.computedStyles.sidebar.minWidth - (sidebarPosition === Position.LEFT ? e.currentX - startX : startX - e.currentX); - this.sidebarWidth = this.computedStyles.sidebar.minWidth; + if ((sidebarPosition === Position.LEFT && e.currentX - startX >= this.partLayoutInfo.sidebar.minWidth) || + (sidebarPosition === Position.RIGHT && startX - e.currentX >= this.partLayoutInfo.sidebar.minWidth)) { + this.startSidebarWidth = this.partLayoutInfo.sidebar.minWidth - (sidebarPosition === Position.LEFT ? e.currentX - startX : startX - e.currentX); + this.sidebarWidth = this.partLayoutInfo.sidebar.minWidth; promise = this.partService.setSideBarHidden(false); } } @@ -191,8 +217,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal if (isPanelVisible) { // Automatically hide panel when a certain threshold is met - if (newSashHeight + HIDE_PANEL_HEIGHT_THRESHOLD < this.computedStyles.panel.minHeight) { - let dragCompensation = DEFAULT_MIN_PANEL_PART_HEIGHT - HIDE_PANEL_HEIGHT_THRESHOLD; + if (newSashHeight + HIDE_PANEL_HEIGHT_THRESHOLD < this.partLayoutInfo.panel.minHeight) { + let dragCompensation = MIN_PANEL_PART_HEIGHT - HIDE_PANEL_HEIGHT_THRESHOLD; promise = this.partService.setPanelHidden(true); startY = Math.min(this.sidebarHeight - this.statusbarHeight - this.titlebarHeight, e.currentY + dragCompensation); this.panelHeight = this.startPanelHeight; // when restoring panel, restore to the panel height we started from @@ -200,16 +226,16 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal // Otherwise size the panel accordingly else { - this.panelHeight = Math.max(this.computedStyles.panel.minHeight, newSashHeight); // Panel can not become smaller than MIN_PART_HEIGHT - doLayout = newSashHeight >= this.computedStyles.panel.minHeight; + this.panelHeight = Math.max(this.partLayoutInfo.panel.minHeight, newSashHeight); // Panel can not become smaller than MIN_PART_HEIGHT + doLayout = newSashHeight >= this.partLayoutInfo.panel.minHeight; } } // Panel hidden else { - if (startY - e.currentY >= this.computedStyles.panel.minHeight) { + if (startY - e.currentY >= this.partLayoutInfo.panel.minHeight) { this.startPanelHeight = 0; - this.panelHeight = this.computedStyles.panel.minHeight; + this.panelHeight = this.partLayoutInfo.panel.minHeight; promise = this.partService.setPanelHidden(false); } } @@ -236,7 +262,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal this.sashX.addListener2('reset', () => { let activeViewlet = this.viewletService.getActiveViewlet(); let optimalWidth = activeViewlet && activeViewlet.getOptimalWidth(); - this.sidebarWidth = Math.max(DEFAULT_MIN_SIDEBAR_PART_WIDTH, optimalWidth || 0); + this.sidebarWidth = Math.max(MIN_SIDEBAR_PART_WIDTH, optimalWidth || 0); this.storageService.store(WorkbenchLayout.sashXWidthSettingsKey, this.sidebarWidth, StorageScope.GLOBAL); this.partService.setSideBarHidden(false).done(() => this.layout(), errors.onUnexpectedError); }); @@ -250,8 +276,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal if (this.workbenchSize && (this.sidebarWidth || this.panelHeight)) { let visibleEditors = this.editorService.getVisibleEditors().length; if (visibleEditors > 1) { - const sidebarOverflow = this.layoutEditorGroupsVertically && (this.workbenchSize.width - this.sidebarWidth < visibleEditors * DEFAULT_MIN_EDITOR_PART_WIDTH); - const panelOverflow = !this.layoutEditorGroupsVertically && (this.workbenchSize.height - this.panelHeight < visibleEditors * DEFAULT_MIN_EDITOR_PART_HEIGHT); + const sidebarOverflow = this.layoutEditorGroupsVertically && (this.workbenchSize.width - this.sidebarWidth < visibleEditors * MIN_EDITOR_PART_WIDTH); + const panelOverflow = !this.layoutEditorGroupsVertically && (this.workbenchSize.height - this.panelHeight < visibleEditors * MIN_EDITOR_PART_HEIGHT); if (sidebarOverflow || panelOverflow) { this.layout(); @@ -271,67 +297,7 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal } } - private relayout(): void { - - // Recompute Styles - this.computeStyle(); - this.editor.getLayout().computeStyle(); - this.sidebar.getLayout().computeStyle(); - this.panel.getLayout().computeStyle(); - - // Trigger Layout - this.layout(); - } - - private computeStyle(): void { - const titlebarStyle = this.titlebar.getContainer().getComputedStyle(); - const sidebarStyle = this.sidebar.getContainer().getComputedStyle(); - const panelStyle = this.panel.getContainer().getComputedStyle(); - const editorStyle = this.editor.getContainer().getComputedStyle(); - const activitybarStyle = this.activitybar.getContainer().getComputedStyle(); - const statusbarStyle = this.statusbar.getContainer().getComputedStyle(); - - // Determine styles by looking into their CSS - this.computedStyles = { - titlebar: { - height: parseInt(titlebarStyle.getPropertyValue('height'), 10) - }, - activitybar: { - width: parseInt(activitybarStyle.getPropertyValue('width'), 10) - }, - sidebar: { - minWidth: parseInt(sidebarStyle.getPropertyValue('min-width'), 10) || DEFAULT_MIN_SIDEBAR_PART_WIDTH - }, - panel: { - minHeight: parseInt(panelStyle.getPropertyValue('min-height'), 10) || DEFAULT_MIN_PANEL_PART_HEIGHT - }, - editor: { - minWidth: parseInt(editorStyle.getPropertyValue('min-width'), 10) || DEFAULT_MIN_EDITOR_PART_WIDTH, - minHeight: DEFAULT_MIN_EDITOR_PART_HEIGHT - }, - statusbar: { - height: parseInt(statusbarStyle.getPropertyValue('height'), 10) - } - }; - - // Always keep the initial computed styles - if (!this.initialComputedStyles) { - this.initialComputedStyles = this.computedStyles; - } - } - public layout(options?: ILayoutOptions): void { - if (options && options.forceStyleRecompute) { - this.computeStyle(); - this.editor.getLayout().computeStyle(); - this.sidebar.getLayout().computeStyle(); - this.panel.getLayout().computeStyle(); - } - - if (!this.computedStyles) { - this.computeStyle(); - } - this.workbenchSize = this.getWorkbenchArea(); const isActivityBarHidden = !this.partService.isVisible(Parts.ACTIVITYBAR_PART); @@ -346,35 +312,35 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal if (isSidebarHidden) { sidebarWidth = 0; } else if (this.sidebarWidth !== -1) { - sidebarWidth = Math.max(this.computedStyles.sidebar.minWidth, this.sidebarWidth); + sidebarWidth = Math.max(this.partLayoutInfo.sidebar.minWidth, this.sidebarWidth); } else { sidebarWidth = this.workbenchSize.width / 5; this.sidebarWidth = sidebarWidth; } - this.statusbarHeight = isStatusbarHidden ? 0 : this.computedStyles.statusbar.height; - this.titlebarHeight = isTitlebarHidden ? 0 : this.initialComputedStyles.titlebar.height / getZoomFactor(); // adjust for zoom prevention + this.statusbarHeight = isStatusbarHidden ? 0 : this.partLayoutInfo.statusbar.height; + this.titlebarHeight = isTitlebarHidden ? 0 : this.partLayoutInfo.titlebar.height / getZoomFactor(); // adjust for zoom prevention this.sidebarHeight = this.workbenchSize.height - this.statusbarHeight - this.titlebarHeight; let sidebarSize = new Dimension(sidebarWidth, this.sidebarHeight); // Activity Bar - this.activitybarWidth = isActivityBarHidden ? 0 : this.computedStyles.activitybar.width; + this.activitybarWidth = isActivityBarHidden ? 0 : this.partLayoutInfo.activitybar.width; let activityBarSize = new Dimension(this.activitybarWidth, sidebarSize.height); // Panel part let panelHeight: number; - const maxPanelHeight = sidebarSize.height - DEFAULT_MIN_EDITOR_PART_HEIGHT; + const maxPanelHeight = sidebarSize.height - MIN_EDITOR_PART_HEIGHT; if (isPanelHidden) { panelHeight = 0; } else if (this.panelHeight > 0) { - panelHeight = Math.min(maxPanelHeight, Math.max(this.computedStyles.panel.minHeight, this.panelHeight)); + panelHeight = Math.min(maxPanelHeight, Math.max(this.partLayoutInfo.panel.minHeight, this.panelHeight)); } else { panelHeight = sidebarSize.height * DEFAULT_PANEL_HEIGHT_COEFFICIENT; } if (options && options.toggleMaximizedPanel) { const heightToSwap = panelHeight; - panelHeight = panelHeight === maxPanelHeight ? Math.max(this.computedStyles.panel.minHeight, Math.min(this.panelHeightBeforeMaximized, maxPanelHeight)) : maxPanelHeight; + panelHeight = panelHeight === maxPanelHeight ? Math.max(this.partLayoutInfo.panel.minHeight, Math.min(this.panelHeightBeforeMaximized, maxPanelHeight)) : maxPanelHeight; this.panelHeightBeforeMaximized = heightToSwap; } const panelDimension = new Dimension(this.workbenchSize.width - sidebarSize.width - activityBarSize.width, panelHeight); @@ -405,8 +371,8 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal } // Assert Sidebar and Editor Size to not overflow - let editorMinWidth = this.computedStyles.editor.minWidth; - let editorMinHeight = this.computedStyles.editor.minHeight; + let editorMinWidth = this.partLayoutInfo.editor.minWidth; + let editorMinHeight = this.partLayoutInfo.editor.minHeight; let visibleEditorCount = this.editorService.getVisibleEditors().length; if (visibleEditorCount > 1) { if (this.layoutEditorGroupsVertically) { @@ -421,14 +387,14 @@ export class WorkbenchLayout implements IVerticalSashLayoutProvider, IHorizontal editorSize.width = editorMinWidth; panelDimension.width = editorMinWidth; sidebarSize.width -= diff; - sidebarSize.width = Math.max(DEFAULT_MIN_SIDEBAR_PART_WIDTH, sidebarSize.width); + sidebarSize.width = Math.max(MIN_SIDEBAR_PART_WIDTH, sidebarSize.width); } if (editorSize.height < editorMinHeight) { let diff = editorMinHeight - editorSize.height; editorSize.height = editorMinHeight; panelDimension.height -= diff; - panelDimension.height = Math.max(DEFAULT_MIN_PANEL_PART_HEIGHT, panelDimension.height); + panelDimension.height = Math.max(MIN_PANEL_PART_HEIGHT, panelDimension.height); } if (!isSidebarHidden) { diff --git a/src/vs/workbench/browser/part.ts b/src/vs/workbench/browser/part.ts index 417066997c5..7a7ad498902 100644 --- a/src/vs/workbench/browser/part.ts +++ b/src/vs/workbench/browser/part.ts @@ -124,12 +124,11 @@ export class PartLayout { } public computeStyle(): void { - const containerStyle = this.container.getComputedStyle(); this.containerStyle = { - borderLeftWidth: parseInt(containerStyle.getPropertyValue('border-left-width'), 10), - borderRightWidth: parseInt(containerStyle.getPropertyValue('border-right-width'), 10), - borderTopWidth: parseInt(containerStyle.getPropertyValue('border-top-width'), 10), - borderBottomWidth: parseInt(containerStyle.getPropertyValue('border-bottom-width'), 10) + borderLeftWidth: 0, + borderRightWidth: 0, + borderTopWidth: 0, + borderBottomWidth: 0 }; if (this.titleArea) { diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index 441ba622d0d..f272385d250 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -662,7 +662,7 @@ export class Workbench implements IPartService { // Layout if (!skipLayout) { - this.workbenchLayout.layout({ forceStyleRecompute: true }); + this.workbenchLayout.layout(); } } @@ -672,7 +672,7 @@ export class Workbench implements IPartService { // Layout if (!skipLayout) { - this.workbenchLayout.layout({ forceStyleRecompute: true }); + this.workbenchLayout.layout(); } } @@ -716,7 +716,7 @@ export class Workbench implements IPartService { // Layout if (!skipLayout) { - this.workbenchLayout.layout({ forceStyleRecompute: true }); + this.workbenchLayout.layout(); } }); } @@ -758,13 +758,13 @@ export class Workbench implements IPartService { // Layout if (!skipLayout) { - this.workbenchLayout.layout({ forceStyleRecompute: true }); + this.workbenchLayout.layout(); } }); } public toggleMaximizedPanel(): void { - this.workbenchLayout.layout({ forceStyleRecompute: true, toggleMaximizedPanel: true }); + this.workbenchLayout.layout({ toggleMaximizedPanel: true }); } public getSideBarPosition(): Position { @@ -787,7 +787,7 @@ export class Workbench implements IPartService { this.sidebarPart.getContainer().addClass(newPositionValue); // Layout - this.workbenchLayout.layout({ forceStyleRecompute: true }); + this.workbenchLayout.layout(); } public dispose(): void { @@ -1107,7 +1107,7 @@ export class Workbench implements IPartService { this.inZenMode.set(this.zenMode.active); if (!skipLayout) { - this.layout({ forceStyleRecompute: true }); + this.layout(); } if (toggleFullScreen) { this.windowService.toggleFullScreen().done(undefined, errors.onUnexpectedError); diff --git a/src/vs/workbench/services/part/common/partService.ts b/src/vs/workbench/services/part/common/partService.ts index c67e28794e8..47cca47baed 100644 --- a/src/vs/workbench/services/part/common/partService.ts +++ b/src/vs/workbench/services/part/common/partService.ts @@ -23,7 +23,6 @@ export enum Position { } export interface ILayoutOptions { - forceStyleRecompute?: boolean; toggleMaximizedPanel?: boolean; }