Skip to content

Commit

Permalink
Merge pull request #422 from mathuo/360-investigate-opening-tabs-in-n…
Browse files Browse the repository at this point in the history
…ew-browser-window

test: add tests
  • Loading branch information
mathuo authored Jan 8, 2024
2 parents 22d5067 + 105be36 commit b78a7a6
Show file tree
Hide file tree
Showing 11 changed files with 1,502 additions and 1,247 deletions.
2,630 changes: 1,403 additions & 1,227 deletions packages/dockview-core/src/__tests__/dockview/dockviewComponent.spec.ts

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion packages/dockview-core/src/__tests__/lifecycle.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { CompositeDisposable, MutableDisposable } from '../lifecycle';
import {
CompositeDisposable,
Disposable,
MutableDisposable,
} from '../lifecycle';

describe('lifecycle', () => {
test('mutable disposable', () => {
Expand Down Expand Up @@ -64,4 +68,16 @@ describe('lifecycle', () => {

expect(cut.checkIsDisposed()).toBeTruthy();
});

test('Disposable.from(...)', () => {
const func = jest.fn();

const disposable = Disposable.from(func);

expect(func).not.toHaveBeenCalled();

disposable.dispose();

expect(func).toHaveBeenCalledTimes(1);
});
});
31 changes: 21 additions & 10 deletions packages/dockview-core/src/api/dockviewGroupPanelApi.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Position } from '../dnd/droptarget';
import { Position, positionToDirection } from '../dnd/droptarget';
import { DockviewComponent } from '../dockview/dockviewComponent';
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel';
import { Emitter, Event } from '../events';
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';

export interface DockviewGroupPanelApi extends GridviewPanelApi {
readonly onDidRenderPositionChange: Event<DockviewGroupPanelFloatingChangeEvent>;
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
readonly location: DockviewGroupLocation;
moveTo(options: { group: DockviewGroupPanel; position?: Position }): void;
moveTo(options: { group?: DockviewGroupPanel; position?: Position }): void;
maximize(): void;
isMaximized(): boolean;
exitMaximized(): void;
Expand All @@ -24,10 +24,10 @@ const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
private _group: DockviewGroupPanel | undefined;

readonly _onDidRenderPositionChange =
readonly _onDidLocationChange =
new Emitter<DockviewGroupPanelFloatingChangeEvent>();
readonly onDidRenderPositionChange: Event<DockviewGroupPanelFloatingChangeEvent> =
this._onDidRenderPositionChange.event;
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
this._onDidLocationChange.event;

get location(): DockviewGroupLocation {
if (!this._group) {
Expand All @@ -39,19 +39,25 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
constructor(id: string, private readonly accessor: DockviewComponent) {
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) {
throw new Error(NOT_INITIALIZED_MESSAGE);
}

const group =
options.group ??
this.accessor.addGroup({
direction: positionToDirection(options.position ?? 'right'),
});

this.accessor.moveGroupOrPanel(
options.group,
group,
this._group.id,
undefined,
options.position ?? 'center'
options.group ? options.position ?? 'center' : 'center'
);
}

Expand All @@ -60,6 +66,11 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
throw new Error(NOT_INITIALIZED_MESSAGE);
}

if (this.location !== 'grid') {
// only grid groups can be maximized
return;
}

this.accessor.maximizeGroup(this._group);
}

Expand Down
18 changes: 16 additions & 2 deletions packages/dockview-core/src/dockview/dockviewComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { directionToPosition, Droptarget, Position } from '../dnd/droptarget';
import { tail, sequenceEquals, remove } from '../array';
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
import { CompositeDisposable } from '../lifecycle';
import { CompositeDisposable, Disposable } from '../lifecycle';
import { Event, Emitter } from '../events';
import { Watermark } from './components/watermark/watermark';
import {
Expand Down Expand Up @@ -58,7 +58,10 @@ import {
DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE,
DEFAULT_FLOATING_GROUP_POSITION,
} from '../constants';
import { DockviewPanelRenderer, OverlayRenderContainer } from '../overlayRenderContainer';
import {
DockviewPanelRenderer,
OverlayRenderContainer,
} from '../overlayRenderContainer';

function getTheme(element: HTMLElement): string | undefined {
function toClassList(element: HTMLElement) {
Expand Down Expand Up @@ -386,6 +389,17 @@ export class DockviewComponent
this.onDidActivePanelChange
)(() => {
this._bufferOnDidLayoutChange.fire();
}),
Disposable.from(() => {
// iterate over a copy of the array since .dispose() mutates the original array
for (const group of [...this._floatingGroups]) {
group.dispose();
}

// iterate over a copy of the array since .dispose() mutates the original array
for (const group of [...this._popoutGroups]) {
group.dispose();
}
})
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export class DockviewGroupPanelModel
break;
}

this.groupPanel.api._onDidRenderPositionChange.fire({
this.groupPanel.api._onDidLocationChange.fire({
location: this.location,
});
}
Expand Down
8 changes: 8 additions & 0 deletions packages/dockview-core/src/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ export namespace Disposable {
// noop
},
};

export function from(func: () => void): IDisposable {
return {
dispose: () => {
func();
},
};
}
}

export class CompositeDisposable {
Expand Down
3 changes: 0 additions & 3 deletions packages/dockview-core/src/popoutWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ export class PopoutWindow extends CompositeDisposable {

this._window = { value: externalWindow, disposable };

const grievingParent = content.parentElement;

const cleanUp = () => {
grievingParent?.appendChild(content);
this._onDidClose.fire();
this._window = null;
};
Expand Down
11 changes: 11 additions & 0 deletions packages/docs/docs/components/dockview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ From within a panel you may say
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
height={600}
sandboxId="popoutgroup-dockview"
Expand Down
24 changes: 23 additions & 1 deletion packages/docs/sandboxes/demo-dockview/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const Icon = (props: {
);
};

const groupControlsComponents = {
const groupControlsComponents: Record<string, React.FC> = {
panel_1: () => {
return <Icon icon="file_download" />;
},
Expand All @@ -130,6 +130,10 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
: 'expand_content'
);

const [popoutIcon, setPopoutIcon] = React.useState<string>(
props.api.location === 'popout' ? 'close_fullscreen' : 'open_in_new'
);

React.useEffect(() => {
const disposable = props.containerApi.onDidMaxmizedGroupChange(() => {
setIcon(
Expand All @@ -139,8 +143,17 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
);
});

const disposable2 = props.api.onDidLocationChange(() => {
setPopoutIcon(
props.api.location === 'popout'
? 'close_fullscreen'
: 'open_in_new'
);
});

return () => {
disposable.dispose();
disposable2.dispose();
};
}, [props.containerApi]);

Expand All @@ -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 (
<div
className="group-control"
Expand All @@ -165,6 +186,7 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
>
{props.isGroupActive && <Icon icon="star" />}
{Component && <Component />}
<Icon icon={popoutIcon} onClick={onClick2} />
<Icon icon={icon} onClick={onClick} />
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/sandboxes/floatinggroup-dockview/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
);

React.useEffect(() => {
const disposable = props.group.api.onDidRenderPositionChange(
const disposable = props.group.api.onDidLocationChange(
(event) => {
setFloating(event.location === 'floating');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/sandboxes/popoutgroup-dockview/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
);

React.useEffect(() => {
const disposable = props.group.api.onDidRenderPositionChange(
const disposable = props.group.api.onDidLocationChange(
(event) => [setPopout(event.location === 'popout')]
);

Expand Down

0 comments on commit b78a7a6

Please sign in to comment.