Merge from master

This commit is contained in:
Raj Musuku
2019-02-21 17:56:04 -08:00
parent 5a146e34fa
commit 666ae11639
11482 changed files with 119352 additions and 255574 deletions

View File

@@ -3,18 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./gridview';
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 { tail2 as tail, equals } 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';
export enum Direction {
export const enum Direction {
Up,
Down,
Left,
@@ -141,10 +139,15 @@ export function getRelativeLocation(rootOrientation: Orientation, location: numb
function indexInParent(element: HTMLElement): number {
const parentElement = element.parentElement;
if (!parentElement) {
throw new Error('Invalid grid element');
}
let el = parentElement.firstElementChild;
let index = 0;
while (el !== element && el !== parentElement.lastElementChild) {
while (el !== element && el !== parentElement.lastElementChild && el) {
el = el.nextElementSibling;
index++;
}
@@ -159,16 +162,22 @@ function indexInParent(element: HTMLElement): number {
* This will break as soon as DOM structures of the Splitview or Gridview change.
*/
function getGridLocation(element: HTMLElement): number[] {
if (/\bmonaco-grid-view\b/.test(element.parentElement.className)) {
const parentElement = element.parentElement;
if (!parentElement) {
throw new Error('Invalid grid element');
}
if (/\bmonaco-grid-view\b/.test(parentElement.className)) {
return [];
}
const index = indexInParent(element.parentElement);
const ancestor = element.parentElement.parentElement.parentElement.parentElement;
const index = indexInParent(parentElement);
const ancestor = parentElement.parentElement!.parentElement!.parentElement!;
return [...getGridLocation(ancestor), index];
}
export enum Sizing {
export const enum Sizing {
Distribute = 'distribute',
Split = 'split'
}
@@ -195,7 +204,7 @@ export class Grid<T extends IView> implements IDisposable {
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 onDidChange(): Event<{ width: number; height: number; } | undefined> { return this.gridview.onDidChange; }
get element(): HTMLElement { return this.gridview.element; }
@@ -256,15 +265,27 @@ export class Grid<T extends IView> implements IDisposable {
throw new Error('Can\'t remove last view');
}
if (!this.views.has(view)) {
throw new Error('View not found');
}
const location = this.getViewLocation(view);
this.gridview.removeView(location, sizing === Sizing.Distribute ? GridViewSizing.Distribute : undefined);
this.views.delete(view);
}
moveView(view: T, sizing: number | Sizing, referenceView: T, direction: Direction): void {
const sourceLocation = this.getViewLocation(view);
const [sourceParentLocation, from] = tail(sourceLocation);
const referenceLocation = this.getViewLocation(referenceView);
const targetLocation = getRelativeLocation(this.gridview.orientation, referenceLocation, direction);
const [targetParentLocation, to] = tail(targetLocation);
if (equals(sourceParentLocation, targetParentLocation)) {
this.gridview.moveView(sourceParentLocation, from, to);
} else {
this.removeView(view, typeof sizing === 'number' ? undefined : sizing);
this.addView(view, sizing, referenceView, direction);
}
}
swapViews(from: T, to: T): void {
const fromLocation = this.getViewLocation(from);
const toLocation = this.getViewLocation(to);
@@ -358,7 +379,7 @@ export interface ISerializableView extends IView {
}
export interface IViewDeserializer<T extends ISerializableView> {
fromJSON(json: object): T;
fromJSON(json: object | null): T;
}
interface InitialLayoutContext<T extends ISerializableView> {
@@ -369,7 +390,7 @@ interface InitialLayoutContext<T extends ISerializableView> {
export interface ISerializedLeafNode {
type: 'leaf';
data: object;
data: object | null;
size: number;
}
@@ -405,18 +426,15 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
throw new Error('Invalid JSON');
}
const type = json.type;
const data = json.data;
if (type === 'branch') {
if (!Array.isArray(data)) {
if (json.type === 'branch') {
if (!Array.isArray(json.data)) {
throw new Error('Invalid JSON: \'data\' property of branch must be an array.');
}
const children: GridNode<T>[] = [];
let offset = 0;
for (const child of data) {
for (const child of json.data) {
if (typeof child.size !== 'number') {
throw new Error('Invalid JSON: \'size\' property of node must be a number.');
}
@@ -431,8 +449,8 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
return { children, box };
} else if (type === 'leaf') {
const view = deserializer.fromJSON(data) as T;
} else if (json.type === 'leaf') {
const view = deserializer.fromJSON(json.data) as T;
return { view, box };
}
@@ -517,13 +535,13 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
const firstLeaves = node.children.map(c => SerializableGrid.getFirstLeaf(c));
for (let i = 1; i < firstLeaves.length; i++) {
const size = orientation === Orientation.VERTICAL ? firstLeaves[i].box.height : firstLeaves[i].box.width;
this.addView(firstLeaves[i].view, size, referenceView, direction);
referenceView = firstLeaves[i].view;
const size = orientation === Orientation.VERTICAL ? firstLeaves[i]!.box.height : firstLeaves[i]!.box.width;
this.addView(firstLeaves[i]!.view, size, referenceView, direction);
referenceView = firstLeaves[i]!.view;
}
for (let i = 0; i < node.children.length; i++) {
this.restoreViews(firstLeaves[i].view, orthogonal(orientation), node.children[i]);
this.restoreViews(firstLeaves[i]!.view, orthogonal(orientation), node.children[i]);
}
}
@@ -601,10 +619,10 @@ function getDimensions(node: ISerializedNode, orientation: Orientation): { width
if (orientation === Orientation.VERTICAL) {
const width = node.size || (childrenDimensions.length === 0 ? undefined : Math.max(...childrenDimensions.map(d => d.width || 0)));
const height = childrenDimensions.length === 0 ? undefined : childrenDimensions.reduce((r, d) => r + d.height, 0);
const height = childrenDimensions.length === 0 ? undefined : childrenDimensions.reduce((r, d) => r + (d.height || 0), 0);
return { width, height };
} else {
const width = childrenDimensions.length === 0 ? undefined : childrenDimensions.reduce((r, d) => r + d.width, 0);
const width = childrenDimensions.length === 0 ? undefined : childrenDimensions.reduce((r, d) => r + (d.width || 0), 0);
const height = node.size || (childrenDimensions.length === 0 ? undefined : Math.max(...childrenDimensions.map(d => d.height || 0)));
return { width, height };
}

View File

@@ -3,18 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./gridview';
import { Event, anyEvent, Emitter, mapEvent, Relay } from 'vs/base/common/event';
import { Orientation, Sash } from 'vs/base/browser/ui/sash/sash';
import { SplitView, IView as ISplitView, Sizing, ISplitViewStyles } from 'vs/base/browser/ui/splitview/splitview';
import { SplitView, IView as ISplitView, Sizing, LayoutPriority, ISplitViewStyles } from 'vs/base/browser/ui/splitview/splitview';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { $ } from 'vs/base/browser/dom';
import { tail2 as tail } from 'vs/base/common/arrays';
import { Color } from 'vs/base/common/color';
export { Sizing } from 'vs/base/browser/ui/splitview/splitview';
export { Sizing, LayoutPriority } from 'vs/base/browser/ui/splitview/splitview';
export { Orientation } from 'vs/base/browser/ui/sash/sash';
export interface IView {
@@ -24,6 +22,8 @@ export interface IView {
readonly minimumHeight: number;
readonly maximumHeight: number;
readonly onDidChange: Event<{ width: number; height: number; }>;
readonly priority?: LayoutPriority;
readonly snapSize?: number;
layout(width: number, height: number): void;
}
@@ -62,6 +62,7 @@ const defaultStyles: IGridViewStyles = {
export interface IGridViewOptions {
styles?: IGridViewStyles;
proportionalLayout?: boolean; // default true
}
class BranchNode implements ISplitView, IDisposable {
@@ -137,6 +138,7 @@ class BranchNode implements ISplitView, IDisposable {
constructor(
readonly orientation: Orientation,
styles: IGridViewStyles,
readonly proportionalLayout: boolean,
size: number = 0,
orthogonalSize: number = 0
) {
@@ -181,9 +183,14 @@ class BranchNode implements ISplitView, IDisposable {
throw new Error('Invalid index');
}
const first = index === 0;
const last = index === this.splitview.length;
this.splitview.addView(node, size, index);
this._addChild(node, index);
this.onDidChildrenChange();
}
private _addChild(node: Node, index: number): void {
const first = index === 0;
const last = index === this.children.length;
this.children.splice(index, 0, node);
node.orthogonalStartSash = this.splitview.sashes[index - 1];
node.orthogonalEndSash = this.splitview.sashes[index];
@@ -195,8 +202,6 @@ class BranchNode implements ISplitView, IDisposable {
if (!last) {
this.children[index + 1].orthogonalStartSash = this.splitview.sashes[index];
}
this.onDidChildrenChange();
}
removeChild(index: number, sizing?: Sizing): void {
@@ -204,10 +209,15 @@ class BranchNode implements ISplitView, IDisposable {
throw new Error('Invalid index');
}
const first = index === 0;
const last = index === this.splitview.length - 1;
this.splitview.removeView(index, sizing);
this.children.splice(index, 1);
this._removeChild(index);
this.onDidChildrenChange();
}
private _removeChild(index: number): Node {
const first = index === 0;
const last = index === this.children.length - 1;
const [child] = this.children.splice(index, 1);
if (!first) {
this.children[index - 1].orthogonalEndSash = this.splitview.sashes[index - 1];
@@ -217,7 +227,30 @@ class BranchNode implements ISplitView, IDisposable {
this.children[index].orthogonalStartSash = this.splitview.sashes[Math.max(index - 1, 0)];
}
this.onDidChildrenChange();
return child;
}
moveChild(from: number, to: number): void {
if (from === to) {
return;
}
if (from < 0 || from >= this.children.length) {
throw new Error('Invalid from index');
}
if (to < 0 || to > this.children.length) {
throw new Error('Invalid to index');
}
if (from < to) {
to--;
}
this.splitview.moveView(from, to);
const child = this._removeChild(from);
this._addChild(child, to);
}
swapChildren(from: number, to: number): void {
@@ -332,6 +365,9 @@ class BranchNode implements ISplitView, IDisposable {
child.dispose();
}
this._onDidChange.dispose();
this._onDidSashReset.dispose();
this.splitviewSashResetDisposable.dispose();
this.childrenSashResetDisposable.dispose();
this.childrenChangeDisposable.dispose();
@@ -418,6 +454,14 @@ class LeafNode implements ISplitView, IDisposable {
return this.orientation === Orientation.HORIZONTAL ? this.maximumHeight : this.maximumWidth;
}
get priority(): LayoutPriority | undefined {
return this.view.priority;
}
get snapSize(): number | undefined {
return this.view.snapSize;
}
get minimumOrthogonalSize(): number {
return this.orientation === Orientation.HORIZONTAL ? this.minimumWidth : this.minimumHeight;
}
@@ -451,7 +495,7 @@ type Node = BranchNode | LeafNode;
function flipNode<T extends Node>(node: T, size: number, orthogonalSize: number): T {
if (node instanceof BranchNode) {
const result = new BranchNode(orthogonal(node.orientation), node.styles, size, orthogonalSize);
const result = new BranchNode(orthogonal(node.orientation), node.styles, node.proportionalLayout, size, orthogonalSize);
let totalSize = 0;
@@ -480,6 +524,7 @@ export class GridView implements IDisposable {
readonly element: HTMLElement;
private styles: IGridViewStyles;
private proportionalLayout: boolean;
private _root: BranchNode;
private onDidSashResetRelay = new Relay<number[]>();
@@ -528,13 +573,14 @@ export class GridView implements IDisposable {
get maximumWidth(): number { return this.root.maximumHeight; }
get maximumHeight(): number { return this.root.maximumHeight; }
private _onDidChange = new Relay<{ width: number; height: number; }>();
private _onDidChange = new Relay<{ width: number; height: number; } | undefined>();
readonly onDidChange = this._onDidChange.event;
constructor(options: IGridViewOptions = {}) {
this.element = $('.monaco-grid-view');
this.styles = options.styles || defaultStyles;
this.root = new BranchNode(Orientation.VERTICAL, this.styles);
this.proportionalLayout = typeof options.proportionalLayout !== 'undefined' ? !!options.proportionalLayout : true;
this.root = new BranchNode(Orientation.VERTICAL, this.styles, this.proportionalLayout);
}
style(styles: IGridViewStyles): void {
@@ -564,7 +610,7 @@ export class GridView implements IDisposable {
const [, parentIndex] = tail(rest);
grandParent.removeChild(parentIndex);
const newParent = new BranchNode(parent.orientation, this.styles, parent.size, parent.orthogonalSize);
const newParent = new BranchNode(parent.orientation, this.styles, this.proportionalLayout, parent.size, parent.orthogonalSize);
grandParent.addChild(newParent, parent.size, parentIndex);
newParent.orthogonalLayout(parent.orthogonalSize);
@@ -648,6 +694,16 @@ export class GridView implements IDisposable {
return node.view;
}
moveView(parentLocation: number[], from: number, to: number): void {
const [, parent] = this.getNode(parentLocation);
if (!(parent instanceof BranchNode)) {
throw new Error('Invalid location');
}
parent.moveChild(from, to);
}
swapViews(from: number[], to: number[]): void {
const [fromRest, fromIndex] = tail(from);
const [, fromParent] = this.getNode(fromRest);