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,10 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./splitview';
import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IDisposable, combinedDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Event, mapEvent, Emitter } from 'vs/base/common/event';
import * as types from 'vs/base/common/types';
import * as dom from 'vs/base/browser/dom';
@@ -31,6 +29,16 @@ export interface ISplitViewOptions {
orthogonalStartSash?: Sash;
orthogonalEndSash?: Sash;
inverseAltBehavior?: boolean;
proportionalLayout?: boolean; // default true
}
/**
* Only used when `proportionalLayout` is false.
*/
export const enum LayoutPriority {
Normal,
Low,
High
}
export interface IView {
@@ -38,6 +46,8 @@ export interface IView {
readonly minimumSize: number;
readonly maximumSize: number;
readonly onDidChange: Event<number | undefined>;
readonly priority?: LayoutPriority;
readonly snapSize?: number;
layout(size: number, orientation: Orientation): void;
}
@@ -86,10 +96,9 @@ export namespace Sizing {
export function Split(index: number): SplitSizing { return { type: 'split', index }; }
}
export class SplitView implements IDisposable {
export class SplitView extends Disposable {
readonly orientation: Orientation;
// TODO@Joao have the same pattern as grid here
readonly el: HTMLElement;
private sashContainer: HTMLElement;
private viewContainer: HTMLElement;
@@ -101,10 +110,12 @@ export class SplitView implements IDisposable {
private sashDragState: ISashDragState;
private state: State = State.Idle;
private inverseAltBehavior: boolean;
private proportionalLayout: boolean;
private _onDidSashChange = new Emitter<number>();
private _onDidSashChange = this._register(new Emitter<number>());
readonly onDidSashChange = this._onDidSashChange.event;
private _onDidSashReset = new Emitter<number>();
private _onDidSashReset = this._register(new Emitter<number>());
readonly onDidSashReset = this._onDidSashReset.event;
get length(): number {
@@ -144,8 +155,11 @@ export class SplitView implements IDisposable {
}
constructor(container: HTMLElement, options: ISplitViewOptions = {}) {
super();
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
this.inverseAltBehavior = !!options.inverseAltBehavior;
this.proportionalLayout = types.isUndefined(options.proportionalLayout) ? true : !!options.proportionalLayout;
this.el = document.createElement('div');
dom.addClass(this.el, 'monaco-split-view2');
@@ -316,8 +330,10 @@ export class SplitView implements IDisposable {
private relayout(lowPriorityIndex?: number, highPriorityIndex?: number): void {
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
const lowPriorityIndexes = typeof lowPriorityIndex === 'number' ? [lowPriorityIndex] : undefined;
const highPriorityIndexes = typeof highPriorityIndex === 'number' ? [highPriorityIndex] : undefined;
this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndex, highPriorityIndex);
this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndexes, highPriorityIndexes);
this.distributeEmptySpace();
this.layoutViews();
this.saveProportions();
@@ -328,11 +344,15 @@ export class SplitView implements IDisposable {
this.size = size;
if (!this.proportions) {
this.resize(this.viewItems.length - 1, size - previousSize);
const indexes = range(this.viewItems.length);
const lowPriorityIndexes = indexes.filter(i => this.viewItems[i].view.priority === LayoutPriority.Low);
const highPriorityIndexes = indexes.filter(i => this.viewItems[i].view.priority === LayoutPriority.High);
this.resize(this.viewItems.length - 1, size - previousSize, undefined, lowPriorityIndexes, highPriorityIndexes);
} else {
for (let i = 0; i < this.viewItems.length; i++) {
const item = this.viewItems[i];
item.size = clamp(Math.round(this.proportions[i] * size), item.view.minimumSize, item.view.maximumSize);
item.size = SplitView.clamp(item, Math.round(this.proportions[i] * size));
}
}
@@ -341,7 +361,7 @@ export class SplitView implements IDisposable {
}
private saveProportions(): void {
if (this.contentSize > 0) {
if (this.proportionalLayout && this.contentSize > 0) {
this.proportions = this.viewItems.map(i => i.size / this.contentSize);
}
}
@@ -424,7 +444,7 @@ export class SplitView implements IDisposable {
}
size = typeof size === 'number' ? size : item.size;
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
size = SplitView.clamp(item, size);
if (this.inverseAltBehavior && index > 0) {
// In this case, we want the view to grow or shrink both sides equally
@@ -499,8 +519,8 @@ export class SplitView implements IDisposable {
index: number,
delta: number,
sizes = this.viewItems.map(i => i.size),
lowPriorityIndex?: number,
highPriorityIndex?: number,
lowPriorityIndexes?: number[],
highPriorityIndexes?: number[],
overloadMinDelta: number = Number.NEGATIVE_INFINITY,
overloadMaxDelta: number = Number.POSITIVE_INFINITY
): number {
@@ -511,14 +531,18 @@ export class SplitView implements IDisposable {
const upIndexes = range(index, -1);
const downIndexes = range(index + 1, this.viewItems.length);
if (typeof highPriorityIndex === 'number') {
pushToStart(upIndexes, highPriorityIndex);
pushToStart(downIndexes, highPriorityIndex);
if (highPriorityIndexes) {
for (const index of highPriorityIndexes) {
pushToStart(upIndexes, index);
pushToStart(downIndexes, index);
}
}
if (typeof lowPriorityIndex === 'number') {
pushToEnd(upIndexes, lowPriorityIndex);
pushToEnd(downIndexes, lowPriorityIndex);
if (lowPriorityIndexes) {
for (const index of lowPriorityIndexes) {
pushToEnd(upIndexes, index);
pushToEnd(downIndexes, index);
}
}
const upItems = upIndexes.map(i => this.viewItems[i]);
@@ -527,27 +551,29 @@ export class SplitView implements IDisposable {
const downItems = downIndexes.map(i => this.viewItems[i]);
const downSizes = downIndexes.map(i => sizes[i]);
const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.minimumSize - sizes[i]), 0);
const minDeltaUp = upIndexes.reduce((r, i) => r + ((typeof this.viewItems[i].view.snapSize === 'number' ? 0 : this.viewItems[i].view.minimumSize) - sizes[i]), 0);
const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - (typeof this.viewItems[i].view.snapSize === 'number' ? 0 : this.viewItems[i].view.minimumSize)), 0);
const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.maximumSize), 0);
const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta);
const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta);
delta = clamp(delta, minDelta, maxDelta);
const tentativeDelta = clamp(delta, minDelta, maxDelta);
let actualDelta = 0;
for (let i = 0, deltaUp = delta; i < upItems.length; i++) {
for (let i = 0, deltaUp = tentativeDelta; i < upItems.length; i++) {
const item = upItems[i];
const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize);
const size = SplitView.clamp(item, upSizes[i] + deltaUp/* , upIndexes[i] === index */);
const viewDelta = size - upSizes[i];
actualDelta += viewDelta;
deltaUp -= viewDelta;
item.size = size;
}
for (let i = 0, deltaDown = delta; i < downItems.length; i++) {
for (let i = 0, deltaDown = actualDelta; i < downItems.length; i++) {
const item = downItems[i];
const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize);
const size = SplitView.clamp(item, downSizes[i] - deltaDown);
const viewDelta = size - downSizes[i];
deltaDown += viewDelta;
@@ -557,13 +583,24 @@ export class SplitView implements IDisposable {
return delta;
}
private static clamp(item: IViewItem, size: number): number {
const result = clamp(size, item.view.minimumSize, item.view.maximumSize);
if (typeof item.view.snapSize !== 'number' || size >= item.view.minimumSize) {
return result;
}
const snapSize = Math.min(item.view.snapSize, item.view.minimumSize);
return size < snapSize ? 0 : item.view.minimumSize;
}
private distributeEmptySpace(): void {
let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
let emptyDelta = this.size - contentSize;
for (let i = this.viewItems.length - 1; emptyDelta !== 0 && i >= 0; i--) {
const item = this.viewItems[i];
const size = clamp(item.size + emptyDelta, item.view.minimumSize, item.view.maximumSize);
const size = SplitView.clamp(item, item.size + emptyDelta);
const viewDelta = size - item.size;
emptyDelta -= viewDelta;
@@ -626,6 +663,8 @@ export class SplitView implements IDisposable {
}
dispose(): void {
super.dispose();
this.viewItems.forEach(i => i.disposable.dispose());
this.viewItems = [];