Merge pull request #157 from mathuo/156-add-doucmentation-for-dockview-resizing

update documentation
This commit is contained in:
mathuo 2022-09-26 21:21:57 +01:00 committed by GitHub
commit 33a52523fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 270 additions and 34 deletions

View File

@ -14,7 +14,10 @@ class Testview implements IView {
private _orthogonalSize = 0; private _orthogonalSize = 0;
private _priority: LayoutPriority | undefined; private _priority: LayoutPriority | undefined;
private readonly _onDidChange = new Emitter<number | undefined>(); private readonly _onDidChange = new Emitter<{
size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange = this._onDidChange.event; readonly onDidChange = this._onDidChange.event;
private readonly _onLayoutCalled = new Emitter<void>(); private readonly _onLayoutCalled = new Emitter<void>();
@ -62,7 +65,7 @@ class Testview implements IView {
this._onLayoutCalled.fire(); this._onLayoutCalled.fire();
} }
fireChangeEvent(value: number | undefined) { fireChangeEvent(value: { size?: number; orthogonalSize?: number }) {
this._onDidChange.fire(value); this._onDidChange.fire(value);
} }
@ -288,17 +291,17 @@ describe('splitview', () => {
expect(view1.size).toBe(100); expect(view1.size).toBe(100);
expect(view2.size).toBe(100); expect(view2.size).toBe(100);
view1.fireChangeEvent(65); view1.fireChangeEvent({ size: 65 });
expect(view1.size).toBe(65); expect(view1.size).toBe(65);
expect(view2.size).toBe(135); expect(view2.size).toBe(135);
view2.fireChangeEvent(75); view2.fireChangeEvent({ size: 75 });
expect(view1.size).toBe(125); expect(view1.size).toBe(125);
expect(view2.size).toBe(75); expect(view2.size).toBe(75);
view2.fireChangeEvent(undefined); view2.fireChangeEvent({});
expect(view1.size).toBe(125); expect(view1.size).toBe(125);
expect(view2.size).toBe(75); expect(view2.size).toBe(75);

View File

@ -697,6 +697,8 @@ export class DockviewComponent
this._onDidDrop.fire({ ...event, api: this._api, group: view }); this._onDidDrop.fire({ ...event, api: this._api, group: view });
}), }),
view.model.onDidAddPanel((event) => { view.model.onDidAddPanel((event) => {
this._onDidAddPanel.fire(event.panel); this._onDidAddPanel.fire(event.panel);
}), }),
view.model.onDidRemovePanel((event) => { view.model.onDidRemovePanel((event) => {

View File

@ -24,8 +24,12 @@ export class BranchNode extends CompositeDisposable implements IView {
private _size: number; private _size: number;
public readonly children: Node[] = []; public readonly children: Node[] = [];
private readonly _onDidChange = new Emitter<number | undefined>(); private readonly _onDidChange = new Emitter<{
readonly onDidChange: Event<number | undefined> = this._onDidChange.event; size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
this._onDidChange.event;
get width(): number { get width(): number {
return this.orientation === Orientation.HORIZONTAL return this.orientation === Orientation.HORIZONTAL
@ -157,7 +161,7 @@ export class BranchNode extends CompositeDisposable implements IView {
this.addDisposables( this.addDisposables(
this._onDidChange, this._onDidChange,
this.splitview.onDidSashEnd(() => { this.splitview.onDidSashEnd(() => {
this._onDidChange.fire(undefined); this._onDidChange.fire({});
}) })
); );
@ -282,12 +286,12 @@ export class BranchNode extends CompositeDisposable implements IView {
this._childrenDisposable = Event.any( this._childrenDisposable = Event.any(
...this.children.map((c) => c.onDidChange) ...this.children.map((c) => c.onDidChange)
)(() => { )((e) => {
/** /**
* indicate a change has occured to allows any re-rendering but don't bubble * indicate a change has occured to allows any re-rendering but don't bubble
* event because that was specific to this branch * event because that was specific to this branch
*/ */
this._onDidChange.fire(undefined); this._onDidChange.fire({ size: e.orthogonalSize });
}); });
} }

View File

@ -269,8 +269,12 @@ export class Gridview implements IDisposable {
public readonly element: HTMLElement; public readonly element: HTMLElement;
private disposable: MutableDisposable = new MutableDisposable(); private disposable: MutableDisposable = new MutableDisposable();
private readonly _onDidChange = new Emitter<number | undefined>(); private readonly _onDidChange = new Emitter<{
readonly onDidChange: Event<number | undefined> = this._onDidChange.event; size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
this._onDidChange.event;
public serialize() { public serialize() {
const root = serializeBranchNode(this.getView(), this.orientation); const root = serializeBranchNode(this.getView(), this.orientation);

View File

@ -13,8 +13,12 @@ import { IGridView } from './gridview';
import { IDisposable } from '../lifecycle'; import { IDisposable } from '../lifecycle';
export class LeafNode implements IView { export class LeafNode implements IView {
private readonly _onDidChange = new Emitter<number | undefined>(); private readonly _onDidChange = new Emitter<{
readonly onDidChange: Event<number | undefined> = this._onDidChange.event; size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
this._onDidChange.event;
private _size: number; private _size: number;
private _orthogonalSize: number; private _orthogonalSize: number;
private _disposable: IDisposable; private _disposable: IDisposable;
@ -102,13 +106,18 @@ export class LeafNode implements IView {
this._disposable = this.view.onDidChange((event) => { this._disposable = this.view.onDidChange((event) => {
if (event) { if (event) {
this._onDidChange.fire( this._onDidChange.fire({
size:
this.orientation === Orientation.VERTICAL this.orientation === Orientation.VERTICAL
? event.width ? event.width
: event.height : event.height,
); orthogonalSize:
this.orientation === Orientation.VERTICAL
? event.height
: event.width,
});
} else { } else {
this._onDidChange.fire(undefined); this._onDidChange.fire({});
} }
}); });
} }
@ -116,7 +125,7 @@ export class LeafNode implements IView {
public setVisible(visible: boolean) { public setVisible(visible: boolean) {
if (this.view.setVisible) { if (this.view.setVisible) {
this.view.setVisible(visible); this.view.setVisible(visible);
this._onDidChange.fire(undefined); this._onDidChange.fire({});
} }
} }

View File

@ -69,8 +69,12 @@ export abstract class PaneviewPanel
{ replay: true } { replay: true }
); );
onDidChangeExpansionState = this._onDidChangeExpansionState.event; onDidChangeExpansionState = this._onDidChangeExpansionState.event;
private readonly _onDidChange = new Emitter<number | undefined>(); private readonly _onDidChange = new Emitter<{
readonly onDidChange: Event<number | undefined> = this._onDidChange.event; size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
this._onDidChange.event;
private headerSize = 22; private headerSize = 22;
private _orthogonalSize = 0; private _orthogonalSize = 0;
@ -171,7 +175,7 @@ export abstract class PaneviewPanel
this.addDisposables( this.addDisposables(
this.api.onDidSizeChange((event) => { this.api.onDidSizeChange((event) => {
this._onDidChange.fire(event.size); this._onDidChange.fire({ size: event.size });
}), }),
addDisposableListener( addDisposableListener(
this.element, this.element,
@ -243,7 +247,7 @@ export abstract class PaneviewPanel
}, 200); }, 200);
} }
this._onDidChange.fire(expanded ? this.width : undefined); this._onDidChange.fire(expanded ? { size: this.width } : {});
this._onDidChangeExpansionState.fire(expanded); this._onDidChangeExpansionState.fire(expanded);
} }

View File

@ -51,7 +51,7 @@ export interface IBaseView {
export interface IView extends IBaseView { export interface IView extends IBaseView {
readonly element: HTMLElement | DocumentFragment; readonly element: HTMLElement | DocumentFragment;
readonly onDidChange: Event<number | undefined>; readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }>;
layout(size: number, orthogonalSize: number): void; layout(size: number, orthogonalSize: number): void;
setVisible(visible: boolean): void; setVisible(visible: boolean): void;
} }
@ -364,7 +364,7 @@ export class Splitview {
} }
const disposable = view.onDidChange((newSize) => const disposable = view.onDidChange((newSize) =>
this.onDidChange(viewItem, newSize) this.onDidChange(viewItem, newSize.size)
); );
const dispose = () => { const dispose = () => {

View File

@ -31,8 +31,12 @@ export abstract class SplitviewPanel
private _orientation?: Orientation; private _orientation?: Orientation;
private readonly _onDidChange = new Emitter<number | undefined>(); private readonly _onDidChange = new Emitter<{
readonly onDidChange: Event<number | undefined> = this._onDidChange.event; size?: number;
orthogonalSize?: number;
}>();
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
this._onDidChange.event;
get priority(): LayoutPriority | undefined { get priority(): LayoutPriority | undefined {
return this._priority; return this._priority;
@ -108,7 +112,7 @@ export abstract class SplitviewPanel
this.updateConstraints(); this.updateConstraints();
}), }),
this.api.onDidSizeChange((event) => { this.api.onDidSizeChange((event) => {
this._onDidChange.fire(event.size); this._onDidChange.fire({ size: event.size });
}) })
); );
} }

View File

@ -12,6 +12,7 @@ import { EventsDockview } from '@site/src/components/dockview/events';
import { ContextMenuDockview } from '@site/src/components/dockview/contextMenu'; import { ContextMenuDockview } from '@site/src/components/dockview/contextMenu';
import { NestedDockview } from '@site/src/components/dockview/nested'; import { NestedDockview } from '@site/src/components/dockview/nested';
import { CustomHeadersDockview } from '@site/src/components/dockview/customHeaders'; import { CustomHeadersDockview } from '@site/src/components/dockview/customHeaders';
import { ResizeDockview } from '@site/src/components/dockview/resize';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
# Dockview # Dockview
@ -150,6 +151,36 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
## Advanced Features ## Advanced Features
### Resizing via API
Each Dockview is comprised of a number of groups, each of which have a number of panels.
Logically most people would want to resize a panel but practically this really translates to resizing the group to which the panel belongs.
From the api you can access the panels group object (`props.group`) which exposes it's own api object (`props.groups.api`).
This api is largly similar to the <Link to="./gridview/#gridview-panel-api">Gridview API</Link>.
To resize an individual panel you could create a snippet similar to below.
```tsx
const onResizePanel = () => {
props.api.group.api.setSize({
height: 100,
});
};
```
```tsx
const onResizePanel = () => {
props.api.group.api.setSize({
width: 100,
});
};
```
Here is a working example of resizing panels via these API methods.
<ResizeDockview />
### Locked group ### Locked group
Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group. Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group.

View File

@ -208,6 +208,10 @@ const config = {
}, },
], ],
}, },
announcementBar: {
id: 'announcementBar', // Increment on change
content: `⭐️ If you like Dockview, give it a star on <a target="_blank" rel="noopener noreferrer" href="https://github.com/mathuo/dockview">GitHub</a>`,
},
}), }),
}; };

View File

@ -209,8 +209,9 @@ const Icon = (props: {
}; };
const Button = () => { const Button = () => {
const [position, setPosition] = const [position, setPosition] = React.useState<
React.useState<{ x: number; y: number } | undefined>(undefined); { x: number; y: number } | undefined
>(undefined);
const close = () => setPosition(undefined); const close = () => setPosition(undefined);
@ -318,6 +319,16 @@ export const DockviewDemo = () => {
event.api.addEmptyGroup(); event.api.addEmptyGroup();
event.api.getPanel('panel_1').api.setActive(); event.api.getPanel('panel_1').api.setActive();
setInterval(() => {
event.api.getPanel('panel_1').update({
params: {
params: {
title: Date.now().toString(),
},
},
});
}, 1000);
}; };
return ( return (

View File

@ -0,0 +1,23 @@
.resize-panel {
padding: 10px;
color: white;
.resize-control {
display: flex;
height: 18px;
line-height: 18px;
font-size: 13px;
span {
width: 60px;
}
input {
width: 75px;
}
button {
width: 50px;
}
}
}

View File

@ -0,0 +1,111 @@
import {
DockviewReact,
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
import './resize.scss';
const Default = (props: IDockviewPanelProps) => {
const [width, setWidth] = React.useState<number>(100);
const [height, setHeight] = React.useState<number>(100);
return (
<div className="resize-panel">
<div style={{ height: '25px' }}>{props.api.title}</div>
<div className="resize-control">
<span>Width:</span>
<input
value={width}
onChange={(e) => setWidth(Number(e.target.value))}
type="number"
min={50}
step={1}
/>
<button
onClick={() => {
props.api.group.api.setSize({
width,
});
}}
>
Set
</button>
</div>
<div className="resize-control">
<span>Height:</span>
<input
value={height}
onChange={(e) => setHeight(Number(e.target.value))}
type="number"
min={50}
step={1}
/>
<button
onClick={() => {
props.api.group.api.setSize({
height,
});
}}
>
Set
</button>
</div>
</div>
);
};
const components = {
default: Default,
};
export const ResizeDockview = () => {
const onReady = (event: DockviewReadyEvent) => {
event.api.addPanel({
id: 'panel_1',
component: 'default',
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
position: {
direction: 'right',
referencePanel: 'panel_1',
},
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
position: {
direction: 'below',
referencePanel: 'panel_1',
},
});
event.api.addPanel({
id: 'panel_4',
component: 'default',
});
event.api.addPanel({
id: 'panel_5',
component: 'default',
});
};
return (
<div
style={{
height: '500px',
display: 'flex',
flexDirection: 'column',
}}
>
<DockviewReact
className="dockview-theme-dark"
onReady={onReady}
components={components}
/>
</div>
);
};

View File

@ -67,8 +67,8 @@ export default function Home(): JSX.Element {
const { siteConfig } = useDocusaurusContext(); const { siteConfig } = useDocusaurusContext();
return ( return (
<Layout <Layout
title={`${siteConfig.title}`} title={`${siteConfig.tagline}`}
description="A zero dependency layout mananger for React." description={`${siteConfig.description}`}
> >
<HomepageHeader2 /> <HomepageHeader2 />
<main className="container"> <main className="container">

View File

@ -150,6 +150,32 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
## Advanced Features ## Advanced Features
### Resizing via API
Each Dockview is comprised of a number of groups, each of which have a number of panels.
Logically most people would want to resize a panel but practically this really translates to resizing the group to which the panel belongs.
From the api you can access the panels group object (`props.group`) which exposes it's own api object (`props.groups.api`).
This api is largly similar to the <Link to="./gridview/#gridview-panel-api">Gridview API</Link>.
To resize an individual panel you could create a snippet similar to below.
```tsx
const onResizePanel = () => {
props.api.group.api.setSize({
height: 100,
});
};
```
```tsx
const onResizePanel = () => {
props.api.group.api.setSize({
width: 100,
});
};
```
### Locked group ### Locked group
Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group. Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group.