未验证 提交 83b1a1c2 编写于 作者: J Joao Moreno

splitview: use TLayoutContext

gridview: propagate top, left in layout
上级 fd16e7cc
......@@ -42,7 +42,7 @@ function toSplitViewView(view: IView, getHeight: () => number): ISplitViewView {
get maximumSize() { return view.maximumWidth; },
get minimumSize() { return view.minimumWidth; },
onDidChange: Event.map(view.onDidChange, e => e && e.width),
layout: size => view.layout(size, getHeight())
layout: (size, offset) => view.layout(size, getHeight(), 0, offset)
};
}
......@@ -81,7 +81,7 @@ export class CenteredViewLayout implements IDisposable {
this.resizeMargins();
}
} else {
this.view.layout(width, height);
this.view.layout(width, height, 0, 0);
}
this.didLayout = true;
}
......
......@@ -30,7 +30,7 @@ export interface IView {
readonly onDidChange: Event<IViewSize | undefined>;
readonly priority?: LayoutPriority;
readonly snap?: boolean;
layout(width: number, height: number): void;
layout(width: number, height: number, top: number, left: number): void;
setVisible?(visible: boolean): void;
}
......@@ -117,11 +117,16 @@ export interface IGridViewOptions {
readonly layoutController?: ILayoutController;
}
class BranchNode implements ISplitView, IDisposable {
interface ILayoutContext {
readonly orthogonalSize: number;
readonly orthogonalOffset: number;
}
class BranchNode implements ISplitView<ILayoutContext>, IDisposable {
readonly element: HTMLElement;
readonly children: Node[] = [];
private splitview: SplitView;
private splitview: SplitView<ILayoutContext>;
private _size: number;
get size(): number { return this._size; }
......@@ -129,6 +134,12 @@ class BranchNode implements ISplitView, IDisposable {
private _orthogonalSize: number;
get orthogonalSize(): number { return this._orthogonalSize; }
private _offset: number = 0;
get offset(): number { return this._offset; }
private _orthogonalOffset: number = 0;
get orthogonalOffset(): number { return this._orthogonalOffset; }
private _styles: IGridViewStyles;
get styles(): IGridViewStyles { return this._styles; }
......@@ -221,7 +232,7 @@ class BranchNode implements ISplitView, IDisposable {
if (!childDescriptors) {
// Normal behavior, we have no children yet, just set up the splitview
this.splitview = new SplitView(this.element, { orientation, styles, proportionalLayout });
this.splitview.layout(size, orthogonalSize);
this.splitview.layout(size, { orthogonalSize, orthogonalOffset: 0 });
} else {
// Reconstruction behavior, we want to reconstruct a splitview
const descriptor = {
......@@ -268,20 +279,23 @@ class BranchNode implements ISplitView, IDisposable {
}
}
layout(size: number, orthogonalSize: number | undefined): void {
layout(size: number, offset: number, ctx: ILayoutContext | undefined): void {
if (!this.layoutController.isLayoutEnabled) {
return;
}
if (typeof orthogonalSize !== 'number') {
if (typeof ctx === 'undefined') {
throw new Error('Invalid state');
}
// branch nodes should flip the normal/orthogonal directions
this._size = orthogonalSize;
this._size = ctx.orthogonalSize;
this._orthogonalSize = size;
this.splitview.layout(orthogonalSize, size);
this.splitview.layout(ctx.orthogonalSize, {
orthogonalSize: size,
orthogonalOffset: offset
});
}
setVisible(visible: boolean): void {
......@@ -511,7 +525,7 @@ class BranchNode implements ISplitView, IDisposable {
}
}
class LeafNode implements ISplitView, IDisposable {
class LeafNode implements ISplitView<ILayoutContext>, IDisposable {
private _size: number = 0;
get size(): number { return this._size; }
......@@ -519,6 +533,12 @@ class LeafNode implements ISplitView, IDisposable {
private _orthogonalSize: number;
get orthogonalSize(): number { return this._orthogonalSize; }
private _offset: number = 0;
get offset(): number { return this._offset; }
private _orthogonalOffset: number = 0;
get orthogonalOffset(): number { return this._orthogonalOffset; }
readonly onDidSashReset: Event<number[]> = Event.None;
private _onDidLinkedWidthNodeChange = new Relay<number | undefined>();
......@@ -565,6 +585,14 @@ class LeafNode implements ISplitView, IDisposable {
return this.orientation === Orientation.HORIZONTAL ? this.size : this.orthogonalSize;
}
get top(): number {
return this.orientation === Orientation.HORIZONTAL ? this.offset : this.orthogonalOffset;
}
get left(): number {
return this.orientation === Orientation.HORIZONTAL ? this.orthogonalOffset : this.offset;
}
get element(): HTMLElement {
return this.view.element;
}
......@@ -617,18 +645,20 @@ class LeafNode implements ISplitView, IDisposable {
// noop
}
layout(size: number, orthogonalSize: number | undefined): void {
layout(size: number, offset: number, ctx: ILayoutContext | undefined): void {
if (!this.layoutController.isLayoutEnabled) {
return;
}
if (typeof orthogonalSize !== 'number') {
if (typeof ctx === 'undefined') {
throw new Error('Invalid state');
}
this._size = size;
this._orthogonalSize = orthogonalSize;
this.view.layout(this.width, this.height);
this._offset = offset;
this._orthogonalSize = ctx.orthogonalSize;
this._orthogonalOffset = ctx.orthogonalOffset;
this.view.layout(this.width, this.height, this.top, this.left);
}
setVisible(visible: boolean): void {
......@@ -715,7 +745,7 @@ export class GridView implements IDisposable {
const { size, orthogonalSize } = this._root;
this.root = flipNode(this._root, orthogonalSize, size);
this.root.layout(size, orthogonalSize);
this.root.layout(size, 0, { orthogonalSize, orthogonalOffset: 0 });
}
get width(): number { return this.root.width; }
......@@ -771,7 +801,7 @@ export class GridView implements IDisposable {
this.firstLayoutController.isLayoutEnabled = true;
const [size, orthogonalSize] = this.root.orientation === Orientation.HORIZONTAL ? [height, width] : [width, height];
this.root.layout(size, orthogonalSize);
this.root.layout(size, 0, { orthogonalSize, orthogonalOffset: 0 });
}
addView(view: IView, size: number | Sizing, location: number[]): void {
......
......@@ -23,14 +23,14 @@ const defaultStyles: ISplitViewStyles = {
separatorBorder: Color.transparent
};
export interface ISplitViewOptions {
export interface ISplitViewOptions<TLayoutContext = undefined> {
readonly orientation?: Orientation; // default Orientation.VERTICAL
readonly styles?: ISplitViewStyles;
readonly orthogonalStartSash?: Sash;
readonly orthogonalEndSash?: Sash;
readonly inverseAltBehavior?: boolean;
readonly proportionalLayout?: boolean; // default true,
readonly descriptor?: ISplitViewDescriptor;
readonly descriptor?: ISplitViewDescriptor<TLayoutContext>;
}
/**
......@@ -42,14 +42,14 @@ export const enum LayoutPriority {
High
}
export interface IView {
export interface IView<TLayoutContext = undefined> {
readonly element: HTMLElement;
readonly minimumSize: number;
readonly maximumSize: number;
readonly onDidChange: Event<number | undefined>;
readonly priority?: LayoutPriority;
readonly snap?: boolean;
layout(size: number, orthogonalSize: number | undefined): void;
layout(size: number, offset: number, context: TLayoutContext | undefined): void;
setVisible?(visible: boolean): void;
}
......@@ -62,7 +62,7 @@ interface ISashEvent {
type ViewItemSize = number | { cachedVisibleSize: number };
abstract class ViewItem {
abstract class ViewItem<TLayoutContext> {
private _size: number;
set size(size: number) {
......@@ -115,7 +115,7 @@ abstract class ViewItem {
constructor(
protected container: HTMLElement,
private view: IView,
private view: IView<TLayoutContext>,
size: ViewItemSize,
private disposable: IDisposable
) {
......@@ -129,31 +129,31 @@ abstract class ViewItem {
}
}
layout(position: number, orthogonalSize: number | undefined): void {
this.layoutContainer(position);
this.view.layout(this.size, orthogonalSize);
layout(offset: number, layoutContext: TLayoutContext | undefined): void {
this.layoutContainer(offset);
this.view.layout(this.size, offset, layoutContext);
}
abstract layoutContainer(position: number): void;
abstract layoutContainer(offset: number): void;
dispose(): IView {
dispose(): IView<TLayoutContext> {
this.disposable.dispose();
return this.view;
}
}
class VerticalViewItem extends ViewItem {
class VerticalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
layoutContainer(position: number): void {
this.container.style.top = `${position}px`;
layoutContainer(offset: number): void {
this.container.style.top = `${offset}px`;
this.container.style.height = `${this.size}px`;
}
}
class HorizontalViewItem extends ViewItem {
class HorizontalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
layoutContainer(position: number): void {
this.container.style.left = `${position}px`;
layoutContainer(offset: number): void {
this.container.style.left = `${offset}px`;
this.container.style.width = `${this.size}px`;
}
}
......@@ -198,26 +198,26 @@ export namespace Sizing {
export function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; }
}
export interface ISplitViewDescriptor {
export interface ISplitViewDescriptor<TLayoutContext> {
size: number;
views: {
visible?: boolean;
size: number;
view: IView;
view: IView<TLayoutContext>;
}[];
}
export class SplitView extends Disposable {
export class SplitView<TLayoutContext = undefined> extends Disposable {
readonly orientation: Orientation;
readonly el: HTMLElement;
private sashContainer: HTMLElement;
private viewContainer: HTMLElement;
private size = 0;
private orthogonalSize: number | undefined;
private layoutContext: TLayoutContext | undefined;
private contentSize = 0;
private proportions: undefined | number[] = undefined;
private viewItems: ViewItem[] = [];
private viewItems: ViewItem<TLayoutContext>[] = [];
private sashItems: ISashItem[] = [];
private sashDragState: ISashDragState | undefined;
private state: State = State.Idle;
......@@ -280,7 +280,7 @@ export class SplitView extends Disposable {
this.updateSashEnablement();
}
constructor(container: HTMLElement, options: ISplitViewOptions = {}) {
constructor(container: HTMLElement, options: ISplitViewOptions<TLayoutContext> = {}) {
super();
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
......@@ -323,11 +323,11 @@ export class SplitView extends Disposable {
}
}
addView(view: IView, size: number | Sizing, index = this.viewItems.length): void {
addView(view: IView<TLayoutContext>, size: number | Sizing, index = this.viewItems.length): void {
this.doAddView(view, size, index, false);
}
removeView(index: number, sizing?: Sizing): IView {
removeView(index: number, sizing?: Sizing): IView<TLayoutContext> {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
......@@ -419,10 +419,10 @@ export class SplitView extends Disposable {
return viewItem.cachedVisibleSize;
}
layout(size: number, orthogonalSize?: number): void {
layout(size: number, layoutContext?: TLayoutContext): void {
const previousSize = Math.max(this.size, this.contentSize);
this.size = size;
this.orthogonalSize = orthogonalSize;
this.layoutContext = layoutContext;
if (!this.proportions) {
const indexes = range(this.viewItems.length);
......@@ -563,7 +563,7 @@ export class SplitView extends Disposable {
}
}
private onViewChange(item: ViewItem, size: number | undefined): void {
private onViewChange(item: ViewItem<TLayoutContext>, size: number | undefined): void {
const index = this.viewItems.indexOf(item);
if (index < 0 || index >= this.viewItems.length) {
......@@ -610,7 +610,7 @@ export class SplitView extends Disposable {
}
distributeViewSizes(): void {
const flexibleViewItems: ViewItem[] = [];
const flexibleViewItems: ViewItem<TLayoutContext>[] = [];
let flexibleSize = 0;
for (const item of this.viewItems) {
......@@ -641,7 +641,7 @@ export class SplitView extends Disposable {
return this.viewItems[index].size;
}
private doAddView(view: IView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
private doAddView(view: IView<TLayoutContext>, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
......@@ -875,11 +875,11 @@ export class SplitView extends Disposable {
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
// Layout views
let position = 0;
let offset = 0;
for (const viewItem of this.viewItems) {
viewItem.layout(position, this.orthogonalSize);
position += viewItem.size;
viewItem.layout(offset, this.layoutContext);
offset += viewItem.size;
}
// Layout sashes
......
......@@ -8,7 +8,7 @@ import { Emitter } from 'vs/base/common/event';
import { SplitView, IView, Sizing, LayoutPriority } from 'vs/base/browser/ui/splitview/splitview';
import { Sash, SashState } from 'vs/base/browser/ui/sash/sash';
class TestView implements IView {
class TestView implements IView<number> {
private readonly _onDidChange = new Emitter<number | undefined>();
readonly onDidChange = this._onDidChange.event;
......@@ -43,7 +43,7 @@ class TestView implements IView {
assert(_minimumSize <= _maximumSize, 'splitview view minimum size must be <= maximum size');
}
layout(size: number, orthogonalSize: number | undefined): void {
layout(size: number, _offset: number, orthogonalSize: number | undefined): void {
this._size = size;
this._orthogonalSize = orthogonalSize;
this._onDidLayout.fire({ size, orthogonalSize });
......@@ -527,11 +527,11 @@ suite('Splitview', () => {
view1.dispose();
});
test('orthogonal size propagates to views', () => {
test('context propagates to views', () => {
const view1 = new TestView(20, Number.POSITIVE_INFINITY);
const view2 = new TestView(20, Number.POSITIVE_INFINITY);
const view3 = new TestView(20, Number.POSITIVE_INFINITY, LayoutPriority.Low);
const splitview = new SplitView(container, { proportionalLayout: false });
const splitview = new SplitView<number>(container, { proportionalLayout: false });
splitview.layout(200);
splitview.addView(view1, Sizing.Distribute);
......
......@@ -18,7 +18,10 @@
color: white;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-weight: bold;
font-size: 30px;
font-size: 20px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
......@@ -65,9 +68,8 @@
this.setVisible(true);
}
layout(width, height, orientation) {
console.log(`layout@${this.label}`);
this.element.style.lineHeight = `${height}px`;
layout(width, height, top, left) {
this.element.innerHTML = `(${top}, ${left})<br />(${width}, ${height})`;
}
setVisible(visible) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册