mirror of
https://github.com/mathuo/dockview
synced 2025-03-12 00:42:04 +00:00
feat: popout groups
This commit is contained in:
parent
aa6eb27d7d
commit
105be3661f
@ -1,4 +1,4 @@
|
|||||||
import { Position } from '../dnd/droptarget';
|
import { Position, positionToDirection } from '../dnd/droptarget';
|
||||||
import { DockviewComponent } from '../dockview/dockviewComponent';
|
import { DockviewComponent } from '../dockview/dockviewComponent';
|
||||||
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
||||||
import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel';
|
import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel';
|
||||||
@ -6,9 +6,9 @@ import { Emitter, Event } from '../events';
|
|||||||
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
|
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
|
||||||
|
|
||||||
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
||||||
readonly onDidRenderPositionChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
||||||
readonly location: DockviewGroupLocation;
|
readonly location: DockviewGroupLocation;
|
||||||
moveTo(options: { group: DockviewGroupPanel; position?: Position }): void;
|
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void;
|
||||||
maximize(): void;
|
maximize(): void;
|
||||||
isMaximized(): boolean;
|
isMaximized(): boolean;
|
||||||
exitMaximized(): void;
|
exitMaximized(): void;
|
||||||
@ -24,10 +24,10 @@ const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
|
|||||||
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
||||||
private _group: DockviewGroupPanel | undefined;
|
private _group: DockviewGroupPanel | undefined;
|
||||||
|
|
||||||
readonly _onDidRenderPositionChange =
|
readonly _onDidLocationChange =
|
||||||
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
|
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
|
||||||
readonly onDidRenderPositionChange: Event<DockviewGroupPanelFloatingChangeEvent> =
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
|
||||||
this._onDidRenderPositionChange.event;
|
this._onDidLocationChange.event;
|
||||||
|
|
||||||
get location(): DockviewGroupLocation {
|
get location(): DockviewGroupLocation {
|
||||||
if (!this._group) {
|
if (!this._group) {
|
||||||
@ -39,19 +39,25 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
constructor(id: string, private readonly accessor: DockviewComponent) {
|
constructor(id: string, private readonly accessor: DockviewComponent) {
|
||||||
super(id);
|
super(id);
|
||||||
|
|
||||||
this.addDisposables(this._onDidRenderPositionChange);
|
this.addDisposables(this._onDidLocationChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTo(options: { group: DockviewGroupPanel; position?: Position }): void {
|
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void {
|
||||||
if (!this._group) {
|
if (!this._group) {
|
||||||
throw new Error(NOT_INITIALIZED_MESSAGE);
|
throw new Error(NOT_INITIALIZED_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const group =
|
||||||
|
options.group ??
|
||||||
|
this.accessor.addGroup({
|
||||||
|
direction: positionToDirection(options.position ?? 'right'),
|
||||||
|
});
|
||||||
|
|
||||||
this.accessor.moveGroupOrPanel(
|
this.accessor.moveGroupOrPanel(
|
||||||
options.group,
|
group,
|
||||||
this._group.id,
|
this._group.id,
|
||||||
undefined,
|
undefined,
|
||||||
options.position ?? 'center'
|
options.group ? options.position ?? 'center' : 'center'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +66,11 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
throw new Error(NOT_INITIALIZED_MESSAGE);
|
throw new Error(NOT_INITIALIZED_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.location !== 'grid') {
|
||||||
|
// only grid groups can be maximized
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.accessor.maximizeGroup(this._group);
|
this.accessor.maximizeGroup(this._group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ export class DockviewGroupPanelModel
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.groupPanel.api._onDidRenderPositionChange.fire({
|
this.groupPanel.api._onDidLocationChange.fire({
|
||||||
location: this.location,
|
location: this.location,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -389,6 +389,17 @@ From within a panel you may say
|
|||||||
props.containerApi.addPopoutGroup(props.api.group);
|
props.containerApi.addPopoutGroup(props.api.group);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To programatically move the popout group back into the main grid you can use the `moveTo` method in many ways, one of the following would suffice
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
// option 1: add absolutely to the right-side of the grid
|
||||||
|
props.group.api.moveTo({position: 'right'});
|
||||||
|
|
||||||
|
// option 2: create a new group and move the contents of the popout group to it
|
||||||
|
const group = props.containerApi.addGroup();
|
||||||
|
props.group.api.moveTo({ group });
|
||||||
|
```
|
||||||
|
|
||||||
<MultiFrameworkContainer
|
<MultiFrameworkContainer
|
||||||
height={600}
|
height={600}
|
||||||
sandboxId="popoutgroup-dockview"
|
sandboxId="popoutgroup-dockview"
|
||||||
|
@ -109,7 +109,7 @@ const Icon = (props: {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupControlsComponents = {
|
const groupControlsComponents: Record<string, React.FC> = {
|
||||||
panel_1: () => {
|
panel_1: () => {
|
||||||
return <Icon icon="file_download" />;
|
return <Icon icon="file_download" />;
|
||||||
},
|
},
|
||||||
@ -130,6 +130,10 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
: 'expand_content'
|
: 'expand_content'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [popoutIcon, setPopoutIcon] = React.useState<string>(
|
||||||
|
props.api.location === 'popout' ? 'close_fullscreen' : 'open_in_new'
|
||||||
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const disposable = props.containerApi.onDidMaxmizedGroupChange(() => {
|
const disposable = props.containerApi.onDidMaxmizedGroupChange(() => {
|
||||||
setIcon(
|
setIcon(
|
||||||
@ -139,8 +143,17 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const disposable2 = props.api.onDidLocationChange(() => {
|
||||||
|
setPopoutIcon(
|
||||||
|
props.api.location === 'popout'
|
||||||
|
? 'close_fullscreen'
|
||||||
|
: 'open_in_new'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
|
disposable2.dispose();
|
||||||
};
|
};
|
||||||
}, [props.containerApi]);
|
}, [props.containerApi]);
|
||||||
|
|
||||||
@ -152,6 +165,14 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onClick2 = () => {
|
||||||
|
if (props.api.location !== 'popout') {
|
||||||
|
props.containerApi.addPopoutGroup(props.group);
|
||||||
|
} else {
|
||||||
|
props.api.moveTo({ position: 'right' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="group-control"
|
className="group-control"
|
||||||
@ -165,6 +186,7 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
|||||||
>
|
>
|
||||||
{props.isGroupActive && <Icon icon="star" />}
|
{props.isGroupActive && <Icon icon="star" />}
|
||||||
{Component && <Component />}
|
{Component && <Component />}
|
||||||
|
<Icon icon={popoutIcon} onClick={onClick2} />
|
||||||
<Icon icon={icon} onClick={onClick} />
|
<Icon icon={icon} onClick={onClick} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -259,7 +259,7 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const disposable = props.group.api.onDidRenderPositionChange(
|
const disposable = props.group.api.onDidLocationChange(
|
||||||
(event) => {
|
(event) => {
|
||||||
setFloating(event.location === 'floating');
|
setFloating(event.location === 'floating');
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const disposable = props.group.api.onDidRenderPositionChange(
|
const disposable = props.group.api.onDidLocationChange(
|
||||||
(event) => [setPopout(event.location === 'popout')]
|
(event) => [setPopout(event.location === 'popout')]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user