提交 a6db3242 编写于 作者: J Joao Moreno

override old splitview

上级 aafc3018
......@@ -14,7 +14,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { $, append, addClass, removeClass, toggleClass, trackFocus } from 'vs/base/browser/dom';
import { firstIndex } from 'vs/base/common/arrays';
import { Color, RGBA } from 'vs/base/common/color';
import { SplitView, IView } from './splitview2';
import { SplitView, IView } from './splitview';
export interface IPanelOptions {
ariaHeaderLabel?: string;
......
......@@ -3,96 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-split-view {
.monaco-split-view2 {
position: relative;
}
.monaco-split-view > .split-view-view {
overflow: hidden;
}
.monaco-split-view.vertical > .split-view-view {
width: 100%;
}
.monaco-split-view.horizontal > .split-view-view {
height: 100%;
}
.monaco-split-view > .split-view-view > .header {
position: relative;
line-height: 22px;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
padding-left: 20px;
.monaco-split-view2 > .split-view-view {
overflow: hidden;
display: flex;
}
.monaco-split-view > .split-view-view > .header.hide {
display: none;
}
/* Bold font style does not go well with CJK fonts */
.monaco-split-view:lang(zh-Hans) > .split-view-view > .header,
.monaco-split-view:lang(zh-Hant) > .split-view-view > .header,
.monaco-split-view:lang(ja) > .split-view-view > .header,
.monaco-split-view:lang(ko) > .split-view-view > .header { font-weight: normal; }
.monaco-split-view > .split-view-view > .header.collapsible {
cursor: pointer;
}
.monaco-split-view > .split-view-view > .header.collapsible {
background-image: url('arrow-collapse.svg');
background-position: 2px center;
background-repeat: no-repeat;
}
.monaco-split-view > .split-view-view > .header.collapsible:not(.collapsed) {
background-image: url('arrow-expand.svg');
background-position: 2px center;
background-repeat: no-repeat;
}
.vs-dark .monaco-split-view > .split-view-view > .header.collapsible {
background-image: url('arrow-collapse-dark.svg');
}
.vs-dark .monaco-split-view > .split-view-view > .header.collapsible:not(.collapsed) {
background-image: url('arrow-expand-dark.svg');
background-position: 2px center;
background-repeat: no-repeat;
}
/* Animation */
.monaco-split-view.animated > .split-view-view {
transition-duration: 0.15s;
-webkit-transition-duration: 0.15s;
-moz-transition-duration: 0.15s;
transition-timing-function: ease-out;
-webkit-transition-timing-function: ease-out;
-moz-transition-timing-function: ease-out;
}
.monaco-split-view.vertical.animated > .split-view-view {
transition-property: height;
-webkit-transition-property: height;
-moz-transition-property: height;
}
.monaco-split-view.horizontal.animated > .split-view-view {
transition-property: width;
-webkit-transition-property: width;
-moz-transition-property: width;
.monaco-split-view2.vertical > .split-view-view {
width: 100%;
}
.hc-black .split-view-view .action-label {
background: none;
.monaco-split-view2.horizontal > .split-view-view {
height: 100%;
}
.hc-black .split-view-view > .header .action-label:before {
top: 4px !important;
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-split-view2 {
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}
.monaco-split-view2 > .split-view-view {
overflow: hidden;
}
.monaco-split-view2.vertical > .split-view-view {
width: 100%;
}
.monaco-split-view2.horizontal > .split-view-view {
height: 100%;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./splitview2';
import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
import Event, { fromEventEmitter, mapEvent } from 'vs/base/common/event';
import types = require('vs/base/common/types');
import dom = require('vs/base/browser/dom');
import { clamp } from 'vs/base/common/numbers';
import { range, firstIndex } from 'vs/base/common/arrays';
import { Sash, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash';
export { Orientation } from 'vs/base/browser/ui/sash/sash';
export interface ISplitViewOptions {
orientation?: Orientation; // default Orientation.VERTICAL
}
export interface IView {
readonly minimumSize: number;
readonly maximumSize: number;
readonly onDidChange: Event<number | undefined>;
render(container: HTMLElement, orientation: Orientation): void;
layout(size: number, orientation: Orientation): void;
}
interface ISashEvent {
sash: Sash;
start: number;
current: number;
}
interface IViewItem {
view: IView;
size: number;
container: HTMLElement;
disposable: IDisposable;
layout(): void;
}
interface ISashItem {
sash: Sash;
disposable: IDisposable;
}
interface ISashDragState {
index: number;
start: number;
sizes: number[];
minDelta: number;
maxDelta: number;
}
export class SplitView implements IDisposable {
private orientation: Orientation;
private el: HTMLElement;
private size = 0;
private contentSize = 0;
private viewItems: IViewItem[] = [];
private sashItems: ISashItem[] = [];
private sashDragState: ISashDragState;
get length(): number {
return this.viewItems.length;
}
constructor(private container: HTMLElement, options: ISplitViewOptions = {}) {
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
this.el = document.createElement('div');
dom.addClass(this.el, 'monaco-split-view2');
dom.addClass(this.el, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal');
container.appendChild(this.el);
}
addView(view: IView, size: number, index = this.viewItems.length): void {
// Add view
const container = dom.$('.split-view-view');
if (index === this.viewItems.length) {
this.el.appendChild(container);
} else {
this.el.insertBefore(container, this.el.children.item(index));
}
const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size));
const containerDisposable = toDisposable(() => this.el.removeChild(container));
const disposable = combinedDisposable([onChangeDisposable, containerDisposable]);
const layoutContainer = this.orientation === Orientation.VERTICAL
? size => item.container.style.height = `${item.size}px`
: size => item.container.style.width = `${item.size}px`;
const layout = () => {
layoutContainer(item.size);
item.view.layout(item.size, this.orientation);
};
size = Math.round(size);
const item: IViewItem = { view, container, size, layout, disposable };
this.viewItems.splice(index, 0, item);
// Add sash
if (this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) };
const sash = new Sash(this.el, layoutProvider, { orientation });
const sashEventMapper = this.orientation === Orientation.VERTICAL
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY })
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX });
const onStart = mapEvent(fromEventEmitter<IBaseSashEvent>(sash, 'start'), sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this);
const onChange = mapEvent(fromEventEmitter<IBaseSashEvent>(sash, 'change'), sashEventMapper);
const onSashChangeDisposable = onChange(this.onSashChange, this);
const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, sash]);
const sashItem: ISashItem = { sash, disposable };
this.sashItems.splice(index - 1, 0, sashItem);
}
view.render(container, this.orientation);
this.relayout();
}
removeView(index: number): void {
if (index < 0 || index >= this.viewItems.length) {
return;
}
// Remove view
const viewItem = this.viewItems.splice(index, 1)[0];
viewItem.disposable.dispose();
// Remove sash
if (this.viewItems.length >= 1) {
const sashIndex = Math.max(index - 1, 0);
const sashItem = this.sashItems.splice(sashIndex, 1)[0];
sashItem.disposable.dispose();
}
this.relayout();
}
moveView(from: number, to: number): void {
if (from < 0 || from >= this.viewItems.length) {
return;
}
if (to < 0 || to >= this.viewItems.length) {
return;
}
if (from === to) {
return;
}
const viewItem = this.viewItems.splice(from, 1)[0];
this.viewItems.splice(to, 0, viewItem);
if (to + 1 < this.viewItems.length) {
this.el.insertBefore(viewItem.container, this.viewItems[to + 1].container);
} else {
this.el.appendChild(viewItem.container);
}
this.layoutViews();
}
private relayout(): void {
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
this.resize(this.viewItems.length - 1, this.contentSize - contentSize);
}
layout(size: number): void {
const previousSize = Math.max(this.size, this.contentSize);
this.size = size;
this.resize(this.viewItems.length - 1, size - previousSize);
}
private onSashStart({ sash, start }: ISashEvent): void {
const index = firstIndex(this.sashItems, item => item.sash === sash);
const sizes = this.viewItems.map(i => i.size);
const upIndexes = range(index, -1);
const collapseUp = upIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
const downIndexes = range(index + 1, this.viewItems.length);
const collapseDown = downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
const minDelta = -Math.min(collapseUp, expandDown);
const maxDelta = Math.min(collapseDown, expandUp);
this.sashDragState = { start, index, sizes, minDelta, maxDelta };
}
private onSashChange({ sash, current }: ISashEvent): void {
const { index, start, sizes, minDelta, maxDelta } = this.sashDragState;
const delta = clamp(current - start, minDelta, maxDelta);
this.resize(index, delta, sizes);
}
private onViewChange(item: IViewItem, size: number | undefined): void {
const index = this.viewItems.indexOf(item);
if (index < 0 || index >= this.viewItems.length) {
return;
}
size = typeof size === 'number' ? size : item.size;
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
item.size = size;
this.relayout();
}
resizeView(index: number, size: number): void {
if (index < 0 || index >= this.viewItems.length) {
return;
}
const item = this.viewItems[index];
size = Math.round(size);
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
let delta = size - item.size;
if (delta !== 0 && index < this.viewItems.length - 1) {
const downIndexes = range(index + 1, this.viewItems.length);
const collapseDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
const deltaDown = clamp(delta, -expandDown, collapseDown);
this.resize(index, deltaDown);
delta -= deltaDown;
}
if (delta !== 0 && index > 0) {
const upIndexes = range(index - 1, -1);
const collapseUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
const deltaUp = clamp(-delta, -collapseUp, expandUp);
this.resize(index - 1, deltaUp);
}
}
getViewSize(index: number): number {
if (index < 0 || index >= this.viewItems.length) {
return -1;
}
return this.viewItems[index].size;
}
private resize(index: number, delta: number, sizes = this.viewItems.map(i => i.size)): void {
if (index < 0 || index >= this.viewItems.length) {
return;
}
if (delta !== 0) {
const upIndexes = range(index, -1);
const up = upIndexes.map(i => this.viewItems[i]);
const upSizes = upIndexes.map(i => sizes[i]);
const downIndexes = range(index + 1, this.viewItems.length);
const down = downIndexes.map(i => this.viewItems[i]);
const downSizes = downIndexes.map(i => sizes[i]);
for (let i = 0, deltaUp = delta; deltaUp !== 0 && i < up.length; i++) {
const item = up[i];
const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - upSizes[i];
deltaUp -= viewDelta;
item.size = size;
}
for (let i = 0, deltaDown = delta; deltaDown !== 0 && i < down.length; i++) {
const item = down[i];
const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - downSizes[i];
deltaDown += viewDelta;
item.size = size;
}
}
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 viewDelta = size - item.size;
emptyDelta -= viewDelta;
item.size = size;
}
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
this.layoutViews();
}
private layoutViews(): void {
this.viewItems.forEach(item => item.layout());
this.sashItems.forEach(item => item.sash.layout());
// Update sashes enablement
let previous = false;
const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous);
previous = false;
const expandsDown = this.viewItems.map(i => previous = (i.view.maximumSize - i.size > 0) || previous);
const reverseViews = [...this.viewItems].reverse();
previous = false;
const collapsesUp = reverseViews.map(i => previous = (i.size - i.view.minimumSize > 0) || previous).reverse();
previous = false;
const expandsUp = reverseViews.map(i => previous = (i.view.maximumSize - i.size > 0) || previous).reverse();
this.sashItems.forEach((s, i) => {
if ((collapsesDown[i] && expandsUp[i + 1]) || (expandsDown[i] && collapsesUp[i + 1])) {
s.sash.enable();
} else {
s.sash.disable();
}
});
}
private getSashPosition(sash: Sash): number {
let position = 0;
for (let i = 0; i < this.sashItems.length; i++) {
position += this.viewItems[i].size;
if (this.sashItems[i].sash === sash) {
return position;
}
}
return 0;
}
dispose(): void {
this.viewItems.forEach(i => i.disposable.dispose());
this.viewItems = [];
this.sashItems.forEach(i => i.disposable.dispose());
this.sashItems = [];
}
}
......@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { Emitter } from 'vs/base/common/event';
import { SplitView, IView, Orientation } from 'vs/base/browser/ui/splitview/splitview2';
import { SplitView, IView, Orientation } from 'vs/base/browser/ui/splitview/splitview';
import { Sash } from 'vs/base/browser/ui/sash/sash';
class TestView implements IView {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册