From 22ba48e81ee29bd40ce4a5a80352b35c133b9b7f Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:17:37 +0000 Subject: [PATCH] feat: locked mode --- .../src/dockview/dockviewComponent.ts | 1 + .../dockview-core/src/dockview/options.ts | 1 + .../src/gridview/baseComponentGridview.ts | 11 +++++ .../dockview-core/src/gridview/branchNode.ts | 14 +++++- .../dockview-core/src/gridview/gridview.ts | 44 ++++++++++++++++--- .../src/splitview/splitview.scss | 6 +++ .../dockview-core/src/splitview/splitview.ts | 11 +++++ packages/dockview/src/dockview/dockview.tsx | 10 +++++ 8 files changed, 90 insertions(+), 8 deletions(-) diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 82e5283a4..2ec7b7272 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -369,6 +369,7 @@ export class DockviewComponent styles: options.styles, parentElement: options.parentElement, disableAutoResizing: options.disableAutoResizing, + locked: options.locked, }); const gready = document.createElement('div'); diff --git a/packages/dockview-core/src/dockview/options.ts b/packages/dockview-core/src/dockview/options.ts index 34ab98989..ade5f7529 100644 --- a/packages/dockview-core/src/dockview/options.ts +++ b/packages/dockview-core/src/dockview/options.ts @@ -101,6 +101,7 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions { defaultRenderer?: DockviewPanelRenderer; debug?: boolean; rootOverlayModel?: DroptargetOverlayModel; + locked?: boolean; } export interface PanelOptions

{ diff --git a/packages/dockview-core/src/gridview/baseComponentGridview.ts b/packages/dockview-core/src/gridview/baseComponentGridview.ts index 2e4159a9b..0e152de00 100644 --- a/packages/dockview-core/src/gridview/baseComponentGridview.ts +++ b/packages/dockview-core/src/gridview/baseComponentGridview.ts @@ -34,6 +34,7 @@ export interface BaseGridOptions { readonly styles?: ISplitviewStyles; readonly parentElement?: HTMLElement; readonly disableAutoResizing?: boolean; + readonly locked?: boolean; } export interface IGridPanelView extends IGridView, IPanel { @@ -133,6 +134,14 @@ export abstract class BaseGrid return this._activeGroup; } + get locked(): boolean { + return this.gridview.locked; + } + + set locked(value: boolean) { + this.gridview.locked = value; + } + constructor(options: BaseGridOptions) { super(options.parentElement, options.disableAutoResizing); @@ -142,6 +151,8 @@ export abstract class BaseGrid options.orientation ); + this.gridview.locked = !!options.locked; + this.element.appendChild(this.gridview.element); this.layout(0, 0, true); // set some elements height/widths diff --git a/packages/dockview-core/src/gridview/branchNode.ts b/packages/dockview-core/src/gridview/branchNode.ts index 8ba96ef05..d0e449e01 100644 --- a/packages/dockview-core/src/gridview/branchNode.ts +++ b/packages/dockview-core/src/gridview/branchNode.ts @@ -131,17 +131,27 @@ export class BranchNode extends CompositeDisposable implements IView { return LayoutPriority.Normal; } + get locked(): boolean { + return this.splitview.locked; + } + + set locked(value: boolean) { + this.splitview.locked = value; + } + constructor( readonly orientation: Orientation, readonly proportionalLayout: boolean, readonly styles: ISplitviewStyles | undefined, size: number, orthogonalSize: number, + disabled: boolean, childDescriptors?: INodeDescriptor[] ) { super(); this._orthogonalSize = orthogonalSize; this._size = size; + this.element = document.createElement('div'); this.element.className = 'branch-node'; @@ -177,6 +187,8 @@ export class BranchNode extends CompositeDisposable implements IView { }); } + this.locked = disabled; + this.addDisposables( this._onDidChange, this._onDidVisibilityChange, @@ -202,7 +214,7 @@ export class BranchNode extends CompositeDisposable implements IView { return this.splitview.isViewVisible(index); } - setChildVisible(index: number, visible: boolean): void { + setChildVisible(index: number, visible: boolean): void { if (index < 0 || index >= this.children.length) { throw new Error('Invalid index'); } diff --git a/packages/dockview-core/src/gridview/gridview.ts b/packages/dockview-core/src/gridview/gridview.ts index f34fe2672..e7f54637d 100644 --- a/packages/dockview-core/src/gridview/gridview.ts +++ b/packages/dockview-core/src/gridview/gridview.ts @@ -41,7 +41,8 @@ function flipNode( node.proportionalLayout, node.styles, size, - orthogonalSize + orthogonalSize, + node.locked ); let totalSize = 0; @@ -273,6 +274,7 @@ export class Gridview implements IDisposable { readonly element: HTMLElement; private _root: BranchNode | undefined; + private _locked = false; private _maximizedNode: LeafNode | undefined = undefined; private readonly disposable: MutableDisposable = new MutableDisposable(); @@ -328,6 +330,30 @@ export class Gridview implements IDisposable { return this.root.maximumHeight; } + get locked(): boolean { + return this._locked; + } + + set locked(value: boolean) { + this._locked = value; + + const branch: Node[] = [this.root]; + + /** + * simple depth-first-search to cover all nodes + * + * @see https://en.wikipedia.org/wiki/Depth-first_search + */ + while (branch.length > 0) { + const node = branch.pop(); + + if (node instanceof BranchNode) { + node.locked = value; + branch.push(...node.children); + } + } + } + maximizedView(): IGridView | undefined { return this._maximizedNode?.view; } @@ -427,7 +453,8 @@ export class Gridview implements IDisposable { this.proportionalLayout, this.styles, this.root.size, - this.root.orthogonalSize + this.root.orthogonalSize, + this._locked ); } @@ -487,8 +514,8 @@ export class Gridview implements IDisposable { this.proportionalLayout, this.styles, node.size, // <- orthogonal size - flips at each depth - orthogonalSize, // <- size - flips at each depth - + orthogonalSize, // <- size - flips at each depth, + this._locked, children ); } else { @@ -540,7 +567,8 @@ export class Gridview implements IDisposable { this.proportionalLayout, this.styles, this.root.orthogonalSize, - this.root.size + this.root.size, + this._locked ); if (oldRoot.children.length === 0) { @@ -655,7 +683,8 @@ export class Gridview implements IDisposable { proportionalLayout, styles, 0, - 0 + 0, + this._locked ); } @@ -739,7 +768,8 @@ export class Gridview implements IDisposable { this.proportionalLayout, this.styles, parent.size, - parent.orthogonalSize + parent.orthogonalSize, + this._locked ); grandParent.addChild(newParent, parent.size, parentIndex); diff --git a/packages/dockview-core/src/splitview/splitview.scss b/packages/dockview-core/src/splitview/splitview.scss index b12b0969a..82c8a7ced 100644 --- a/packages/dockview-core/src/splitview/splitview.scss +++ b/packages/dockview-core/src/splitview/splitview.scss @@ -25,6 +25,12 @@ height: 100%; width: 100%; + &.dv-splitview-locked { + & > .sash-container > .sash { + pointer-events: none; + } + } + &.animation { .view, .sash { diff --git a/packages/dockview-core/src/splitview/splitview.ts b/packages/dockview-core/src/splitview/splitview.ts index c8b3fdf66..4c5ef3707 100644 --- a/packages/dockview-core/src/splitview/splitview.ts +++ b/packages/dockview-core/src/splitview/splitview.ts @@ -109,6 +109,7 @@ export class Splitview { private proportionalLayout: boolean; private _startSnappingEnabled = true; private _endSnappingEnabled = true; + private _disabled = false; private readonly _onDidSashEnd = new Emitter(); readonly onDidSashEnd = this._onDidSashEnd.event; @@ -200,6 +201,16 @@ export class Splitview { this.updateSashEnablement(); } + get locked(): boolean { + return this._disabled; + } + + set locked(value: boolean) { + this._disabled = value; + + toggleClass(this.element, 'dv-splitview-locked', value); + } + constructor( private readonly container: HTMLElement, options: SplitViewOptions diff --git a/packages/dockview/src/dockview/dockview.tsx b/packages/dockview/src/dockview/dockview.tsx index 91aaa0562..f0012c1ca 100644 --- a/packages/dockview/src/dockview/dockview.tsx +++ b/packages/dockview/src/dockview/dockview.tsx @@ -81,6 +81,7 @@ export interface IDockviewReactProps { debug?: boolean; defaultRenderer?: DockviewPanelRenderer; rootOverlayModel?: DroptargetOverlayModel; + locked?: boolean; } const DEFAULT_REACT_TAB = 'props.defaultTabComponent'; @@ -183,6 +184,7 @@ export const DockviewReact = React.forwardRef( defaultRenderer: props.defaultRenderer, debug: props.debug, rootOverlayModel: props.rootOverlayModel, + locked: props.locked, }); const { clientWidth, clientHeight } = domRef.current; @@ -199,6 +201,14 @@ export const DockviewReact = React.forwardRef( }; }, []); + React.useEffect(() => { + if (!dockviewRef.current) { + return; + } + + dockviewRef.current.locked = !!props.locked; + }, [props.locked]); + React.useEffect(() => { if (!dockviewRef.current) { return () => {