Skip to content

Commit 7b0cc49

Browse files
authored
Merge pull request #508 from mathuo/479-is-there-any-way-to-focus-the-panel-content
feat: fixes
2 parents 53de69a + ed40e22 commit 7b0cc49

File tree

3 files changed

+126
-58
lines changed

3 files changed

+126
-58
lines changed

packages/dockview-core/src/dockview/components/panel/content.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ export class ContentContainer
199199
public closePanel(): void {
200200
if (this.panel) {
201201
if (this.panel.api.renderer === 'onlyWhenVisibile') {
202-
this._element.removeChild(this.panel.view.content.element);
202+
this.panel.view.content.element.parentElement?.removeChild(
203+
this.panel.view.content.element
204+
);
203205
}
204206
}
205207
this.panel = undefined;

packages/dockview-core/src/dockview/dockviewComponent.ts

+115-55
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = {
7171
size: { type: 'pixels', value: 20 },
7272
};
7373

74+
function moveGroupWithoutDestroying(options: {
75+
from: DockviewGroupPanel;
76+
to: DockviewGroupPanel;
77+
}) {
78+
const activePanel = options.from.activePanel;
79+
const panels = [...options.from.panels].map((panel) => {
80+
const removedPanel = options.from.model.removePanel(panel);
81+
options.from.model.renderContainer.detatch(panel);
82+
return removedPanel;
83+
});
84+
85+
panels.forEach((panel) => {
86+
options.to.model.openPanel(panel, {
87+
skipSetActive: activePanel !== panel,
88+
skipSetGroupActive: true,
89+
});
90+
});
91+
}
92+
7493
function getDockviewTheme(element: HTMLElement): string | undefined {
7594
function toClassList(element: HTMLElement) {
7695
const list: string[] = [];
@@ -358,8 +377,8 @@ export class DockviewComponent
358377
private readonly _popoutGroups: {
359378
window: PopoutWindow;
360379
popoutGroup: DockviewGroupPanel;
361-
referenceGroup: string;
362-
disposable: IDisposable;
380+
referenceGroup?: string;
381+
disposable: { dispose: () => DockviewGroupPanel | undefined };
363382
}[] = [];
364383
private readonly _rootDropTarget: Droptarget;
365384

@@ -621,22 +640,6 @@ export class DockviewComponent
621640
const theme = getDockviewTheme(this.gridview.element);
622641
const element = this.element;
623642

624-
function moveGroupWithoutDestroying(options: {
625-
from: DockviewGroupPanel;
626-
to: DockviewGroupPanel;
627-
}) {
628-
const activePanel = options.from.activePanel;
629-
const panels = [...options.from.panels].map((panel) =>
630-
options.from.model.removePanel(panel)
631-
);
632-
633-
panels.forEach((panel) => {
634-
options.to.model.openPanel(panel, {
635-
skipSetActive: activePanel !== panel,
636-
});
637-
});
638-
}
639-
640643
function getBox(): Box {
641644
if (options?.position) {
642645
return options.position;
@@ -657,7 +660,9 @@ export class DockviewComponent
657660
const groupId =
658661
options?.overridePopoutGroup?.id ?? this.getNextGroupId(); //item.id;
659662

660-
itemToPopout.api.setHidden(true);
663+
if (itemToPopout.api.location.type === 'grid') {
664+
itemToPopout.api.setHidden(true);
665+
}
661666

662667
const _window = new PopoutWindow(
663668
`${this.id}-${groupId}`, // unique id
@@ -704,6 +709,8 @@ export class DockviewComponent
704709
? itemToPopout.group
705710
: itemToPopout;
706711

712+
const referenceLocation = itemToPopout.api.location.type;
713+
707714
const group =
708715
options?.overridePopoutGroup ??
709716
this.createGroup({ id: groupId });
@@ -713,23 +720,29 @@ export class DockviewComponent
713720
this._onDidAddGroup.fire(group);
714721
}
715722

716-
const isMoving = this._moving;
717-
718-
try {
719-
this._moving = true;
720-
if (itemToPopout instanceof DockviewPanel) {
723+
if (itemToPopout instanceof DockviewPanel) {
724+
this.movingLock(() => {
721725
const panel =
722726
referenceGroup.model.removePanel(itemToPopout);
723727
group.model.openPanel(panel);
724-
} else {
728+
});
729+
} else {
730+
this.movingLock(() =>
725731
moveGroupWithoutDestroying({
726732
from: referenceGroup,
727733
to: group,
728-
});
729-
referenceGroup.api.setHidden(true);
734+
})
735+
);
736+
737+
switch (referenceLocation) {
738+
case 'grid':
739+
referenceGroup.api.setHidden(true);
740+
break;
741+
case 'floating':
742+
case 'popout':
743+
this.removeGroup(referenceGroup);
744+
break;
730745
}
731-
} finally {
732-
this._moving = isMoving;
733746
}
734747

735748
popoutContainer.classList.add('dv-dockview');
@@ -743,6 +756,8 @@ export class DockviewComponent
743756
getWindow: () => _window.window!,
744757
};
745758

759+
this.doSetGroupAndPanelActive(group);
760+
746761
popoutWindowDisposable.addDisposables(
747762
group.api.onDidActiveChange((event) => {
748763
if (event.isActive) {
@@ -754,11 +769,20 @@ export class DockviewComponent
754769
})
755770
);
756771

772+
let returnedGroup: DockviewGroupPanel | undefined;
773+
757774
const value = {
758775
window: _window,
759776
popoutGroup: group,
760-
referenceGroup: referenceGroup.id,
761-
disposable: popoutWindowDisposable,
777+
referenceGroup: this.getPanel(referenceGroup.id)
778+
? referenceGroup.id
779+
: undefined,
780+
disposable: {
781+
dispose: () => {
782+
popoutWindowDisposable.dispose();
783+
return returnedGroup;
784+
},
785+
},
762786
};
763787

764788
popoutWindowDisposable.addDisposables(
@@ -777,23 +801,22 @@ export class DockviewComponent
777801
overlayRenderContainer,
778802
Disposable.from(() => {
779803
if (this.getPanel(referenceGroup.id)) {
780-
try {
781-
this._moving = true;
804+
this.movingLock(() =>
782805
moveGroupWithoutDestroying({
783806
from: group,
784807
to: referenceGroup,
785-
});
786-
} finally {
787-
this._moving = isMoving;
788-
}
808+
})
809+
);
789810

790811
if (referenceGroup.api.isHidden) {
791812
referenceGroup.api.setHidden(false);
792813
}
793814

794-
this.doRemoveGroup(group, {
795-
skipPopoutAssociated: true,
796-
});
815+
if (this.getPanel(group.id)) {
816+
this.doRemoveGroup(group, {
817+
skipPopoutAssociated: true,
818+
});
819+
}
797820
} else {
798821
if (this.getPanel(group.id)) {
799822
const removedGroup = this.doRemoveGroup(group, {
@@ -803,8 +826,7 @@ export class DockviewComponent
803826
removedGroup.model.renderContainer =
804827
this.overlayRenderContainer;
805828
removedGroup.model.location = { type: 'grid' };
806-
this.doAddGroup(removedGroup, [0]);
807-
this.doSetGroupAndPanelActive(removedGroup);
829+
returnedGroup = removedGroup;
808830
}
809831
}
810832
})
@@ -845,12 +867,40 @@ export class DockviewComponent
845867
} else {
846868
group = item;
847869

870+
const popoutReferenceGroupId = this._popoutGroups.find(
871+
(_) => _.popoutGroup === group
872+
)?.referenceGroup;
873+
const popoutReferenceGroup = popoutReferenceGroupId
874+
? this.getPanel(popoutReferenceGroupId)
875+
: undefined;
876+
848877
const skip =
849878
typeof options?.skipRemoveGroup === 'boolean' &&
850879
options.skipRemoveGroup;
851880

852881
if (!skip) {
853-
this.doRemoveGroup(item, { skipDispose: true });
882+
if (popoutReferenceGroup) {
883+
this.movingLock(() =>
884+
moveGroupWithoutDestroying({
885+
from: item,
886+
to: popoutReferenceGroup,
887+
})
888+
);
889+
this.doRemoveGroup(item, {
890+
skipPopoutReturn: true,
891+
skipPopoutAssociated: true,
892+
});
893+
this.doRemoveGroup(popoutReferenceGroup, {
894+
skipDispose: true,
895+
});
896+
group = popoutReferenceGroup;
897+
} else {
898+
this.doRemoveGroup(item, {
899+
skipDispose: true,
900+
skipPopoutReturn: true,
901+
skipPopoutAssociated: !!popoutReferenceGroup,
902+
});
903+
}
854904
}
855905
}
856906

@@ -1505,7 +1555,7 @@ export class DockviewComponent
15051555
});
15061556

15071557
if (!options.skipDispose) {
1508-
this.overlayRenderContainer.detatch(panel);
1558+
panel.group.model.renderContainer.detatch(panel);
15091559
panel.dispose();
15101560
}
15111561

@@ -1628,6 +1678,8 @@ export class DockviewComponent
16281678
| {
16291679
skipActive?: boolean;
16301680
skipDispose?: boolean;
1681+
skipPopoutAssociated?: boolean;
1682+
skipPopoutReturn?: boolean;
16311683
}
16321684
| undefined
16331685
): void {
@@ -1641,6 +1693,7 @@ export class DockviewComponent
16411693
skipActive?: boolean;
16421694
skipDispose?: boolean;
16431695
skipPopoutAssociated?: boolean;
1696+
skipPopoutReturn?: boolean;
16441697
}
16451698
| undefined
16461699
): DockviewGroupPanel {
@@ -1694,20 +1747,26 @@ export class DockviewComponent
16941747
if (selectedGroup) {
16951748
if (!options?.skipDispose) {
16961749
if (!options?.skipPopoutAssociated) {
1697-
const refGroup = this.getPanel(
1698-
selectedGroup.referenceGroup
1699-
);
1750+
const refGroup = selectedGroup.referenceGroup
1751+
? this.getPanel(selectedGroup.referenceGroup)
1752+
: undefined;
17001753
if (refGroup) {
17011754
this.removeGroup(refGroup);
17021755
}
17031756
}
17041757

17051758
selectedGroup.popoutGroup.dispose();
1759+
17061760
this._groups.delete(group.id);
17071761
this._onDidRemoveGroup.fire(group);
17081762
}
17091763

1710-
selectedGroup.disposable.dispose();
1764+
const removedGroup = selectedGroup.disposable.dispose();
1765+
1766+
if (!options?.skipPopoutReturn && removedGroup) {
1767+
this.doAddGroup(removedGroup, [0]);
1768+
this.doSetGroupAndPanelActive(removedGroup);
1769+
}
17111770

17121771
if (!options?.skipActive && this._activeGroup === group) {
17131772
const groups = Array.from(this._groups.values());
@@ -1993,17 +2052,18 @@ export class DockviewComponent
19932052
}
19942053

19952054
doSetGroupAndPanelActive(group: DockviewGroupPanel | undefined): void {
1996-
// if (
1997-
// this.activeGroup === group &&
1998-
// this._onDidActiveGroupChange.value !== group
1999-
// ) {
2000-
// this._onDidActiveGroupChange.fire(group);
2001-
// }
2002-
20032055
super.doSetGroupActive(group);
20042056

20052057
const activePanel = this.activePanel;
20062058

2059+
if (
2060+
group &&
2061+
this.hasMaximizedGroup() &&
2062+
!this.isMaximizedGroup(group)
2063+
) {
2064+
this.exitMaximizedGroup();
2065+
}
2066+
20072067
if (
20082068
!this._moving &&
20092069
activePanel !== this._onDidActivePanelChange.value

packages/dockview-core/src/overlayRenderContainer.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export class OverlayRenderContainer extends CompositeDisposable {
2828
}
2929
> = {};
3030

31+
private _disposed = false;
32+
3133
constructor(private readonly element: HTMLElement) {
3234
super();
3335

@@ -37,6 +39,7 @@ export class OverlayRenderContainer extends CompositeDisposable {
3739
value.disposable.dispose();
3840
value.destroy.dispose();
3941
}
42+
this._disposed = true;
4043
})
4144
);
4245
}
@@ -149,8 +152,11 @@ export class OverlayRenderContainer extends CompositeDisposable {
149152
);
150153

151154
this.map[panel.api.id].destroy = Disposable.from(() => {
152-
focusContainer.removeChild(panel.view.content.element);
153-
this.element.removeChild(focusContainer);
155+
if (panel.view.content.element.parentElement === focusContainer) {
156+
focusContainer.removeChild(panel.view.content.element);
157+
}
158+
159+
focusContainer.parentElement?.removeChild(focusContainer);
154160
});
155161

156162
queueMicrotask(() => {

0 commit comments

Comments
 (0)