mirror of
https://github.com/mathuo/dockview
synced 2025-09-01 23:16:25 +00:00
Merge branch '170-allow-dnd-of-entire-dockview-groups' of https://github.com/mathuo/dockview into 176-dnd-to-edge-of-dockview
This commit is contained in:
commit
78336d6d90
@ -3,7 +3,7 @@ import { DragHandler } from '../../dnd/abstractDragHandler';
|
||||
import { IDisposable } from '../../lifecycle';
|
||||
|
||||
describe('abstractDragHandler', () => {
|
||||
test('that className dragged is added to element after dragstart event', () => {
|
||||
test('that className dv-dragged is added to element after dragstart event', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const element = document.createElement('div');
|
||||
@ -26,13 +26,13 @@ describe('abstractDragHandler', () => {
|
||||
}
|
||||
})(element);
|
||||
|
||||
expect(element.classList.contains('dragged')).toBeFalsy();
|
||||
expect(element.classList.contains('dv-dragged')).toBeFalsy();
|
||||
|
||||
fireEvent.dragStart(element);
|
||||
expect(element.classList.contains('dragged')).toBeTruthy();
|
||||
expect(element.classList.contains('dv-dragged')).toBeTruthy();
|
||||
|
||||
jest.runAllTimers();
|
||||
expect(element.classList.contains('dragged')).toBeFalsy();
|
||||
expect(element.classList.contains('dv-dragged')).toBeFalsy();
|
||||
|
||||
handler.dispose();
|
||||
});
|
||||
|
@ -34,8 +34,8 @@ export abstract class DragHandler extends CompositeDisposable {
|
||||
iframe.style.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
this.el.classList.add('dragged');
|
||||
setTimeout(() => this.el.classList.remove('dragged'), 0);
|
||||
this.el.classList.add('dv-dragged');
|
||||
setTimeout(() => this.el.classList.remove('dv-dragged'), 0);
|
||||
|
||||
this.disposable.value = this.getData(event.dataTransfer);
|
||||
|
||||
|
@ -5,7 +5,7 @@ export function addGhostImage(
|
||||
ghostElement: HTMLElement
|
||||
) {
|
||||
// class dockview provides to force ghost image to be drawn on a different layer and prevent weird rendering issues
|
||||
addClasses(ghostElement, 'dragged');
|
||||
addClasses(ghostElement, 'dv-dragged');
|
||||
|
||||
document.body.appendChild(ghostElement);
|
||||
dataTransfer.setDragImage(ghostElement, 0, 0);
|
||||
|
60
packages/dockview/src/dnd/groupDragHandler.ts
Normal file
60
packages/dockview/src/dnd/groupDragHandler.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { GroupPanel } from '../groupview/groupviewPanel';
|
||||
import { IDisposable } from '../lifecycle';
|
||||
import { DragHandler } from './abstractDragHandler';
|
||||
import { LocalSelectionTransfer, PanelTransfer } from './dataTransfer';
|
||||
import { addGhostImage } from './ghost';
|
||||
|
||||
export class GroupDragHandler extends DragHandler {
|
||||
private readonly panelTransfer =
|
||||
LocalSelectionTransfer.getInstance<PanelTransfer>();
|
||||
|
||||
constructor(
|
||||
element: HTMLElement,
|
||||
private readonly accessorId: string,
|
||||
private readonly group: GroupPanel
|
||||
) {
|
||||
super(element);
|
||||
}
|
||||
|
||||
getData(dataTransfer: DataTransfer | null): IDisposable {
|
||||
this.panelTransfer.setData(
|
||||
[new PanelTransfer(this.accessorId, this.group.id, null)],
|
||||
PanelTransfer.prototype
|
||||
);
|
||||
|
||||
const style = window.getComputedStyle(this.el);
|
||||
|
||||
const bgColor = style.getPropertyValue(
|
||||
'--dv-activegroup-visiblepanel-tab-background-color'
|
||||
);
|
||||
const color = style.getPropertyValue(
|
||||
'--dv-activegroup-visiblepanel-tab-color'
|
||||
);
|
||||
|
||||
if (dataTransfer) {
|
||||
const ghostElement = document.createElement('div');
|
||||
|
||||
ghostElement.style.backgroundColor = bgColor;
|
||||
ghostElement.style.color = color;
|
||||
ghostElement.style.padding = '2px 8px';
|
||||
ghostElement.style.height = '24px';
|
||||
ghostElement.style.fontSize = '11px';
|
||||
ghostElement.style.lineHeight = '20px';
|
||||
ghostElement.style.borderRadius = '12px';
|
||||
ghostElement.style.position = 'absolute';
|
||||
ghostElement.textContent = `Multiple Panels (${this.group.size})`;
|
||||
|
||||
addGhostImage(dataTransfer, ghostElement);
|
||||
}
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this.panelTransfer.clearData(PanelTransfer.prototype);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
//
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
.dragged {
|
||||
.dv-dragged {
|
||||
transform: translate3d(
|
||||
0px,
|
||||
0px,
|
||||
@ -9,7 +9,7 @@
|
||||
.tab {
|
||||
flex-shrink: 0;
|
||||
|
||||
&.dragging {
|
||||
&.dv-tab-dragging {
|
||||
.tab-action {
|
||||
background-color: var(--dv-activegroup-visiblepanel-tab-color);
|
||||
}
|
||||
|
@ -1,15 +1,3 @@
|
||||
.custom-dragging {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
font-size: 11px;
|
||||
width: 100px;
|
||||
background-color: dodgerblue;
|
||||
color: ghostwhite;
|
||||
border-radius: 11px;
|
||||
position: absolute;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.groupview {
|
||||
&.active-group {
|
||||
> .tabs-and-actions-container > .tabs-container > .tab {
|
||||
@ -50,7 +38,7 @@
|
||||
* therefore we also set some stylings for the dragging event
|
||||
**/
|
||||
.tab {
|
||||
&.dragging {
|
||||
&.dv-tab-dragging {
|
||||
background-color: var(
|
||||
--dv-activegroup-visiblepanel-tab-background-color
|
||||
);
|
||||
|
@ -702,43 +702,8 @@ export class DockviewComponent
|
||||
|
||||
if (itemId === undefined) {
|
||||
if (sourceGroup) {
|
||||
if (!target || target === Position.Center) {
|
||||
const activePanel = sourceGroup.activePanel;
|
||||
const panels = [...sourceGroup.panels].map((p) =>
|
||||
sourceGroup.model.removePanel(p.id)
|
||||
);
|
||||
|
||||
if (sourceGroup?.model.size === 0) {
|
||||
this.doRemoveGroup(sourceGroup);
|
||||
}
|
||||
|
||||
for (const panel of panels) {
|
||||
referenceGroup.model.openPanel(panel, {
|
||||
skipSetPanelActive: panel !== activePanel,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.gridview.removeView(
|
||||
getGridLocation(sourceGroup.element)
|
||||
);
|
||||
|
||||
const referenceLocation = getGridLocation(
|
||||
referenceGroup.element
|
||||
);
|
||||
const dropLocation = getRelativeLocation(
|
||||
this.gridview.orientation,
|
||||
referenceLocation,
|
||||
target
|
||||
);
|
||||
|
||||
this.gridview.addView(
|
||||
sourceGroup,
|
||||
Sizing.Distribute,
|
||||
dropLocation
|
||||
);
|
||||
}
|
||||
this.moveGroup(sourceGroup, referenceGroup, target);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -815,6 +780,48 @@ export class DockviewComponent
|
||||
}
|
||||
}
|
||||
|
||||
private moveGroup(
|
||||
sourceGroup: GroupPanel,
|
||||
referenceGroup: GroupPanel,
|
||||
target: Position
|
||||
): void {
|
||||
if (sourceGroup) {
|
||||
if (!target || target === Position.Center) {
|
||||
const activePanel = sourceGroup.activePanel;
|
||||
const panels = [...sourceGroup.panels].map((p) =>
|
||||
sourceGroup.model.removePanel(p.id)
|
||||
);
|
||||
|
||||
if (sourceGroup?.model.size === 0) {
|
||||
this.doRemoveGroup(sourceGroup);
|
||||
}
|
||||
|
||||
for (const panel of panels) {
|
||||
referenceGroup.model.openPanel(panel, {
|
||||
skipSetPanelActive: panel !== activePanel,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.gridview.removeView(getGridLocation(sourceGroup.element));
|
||||
|
||||
const referenceLocation = getGridLocation(
|
||||
referenceGroup.element
|
||||
);
|
||||
const dropLocation = getRelativeLocation(
|
||||
this.gridview.orientation,
|
||||
referenceLocation,
|
||||
target
|
||||
);
|
||||
|
||||
this.gridview.addView(
|
||||
sourceGroup,
|
||||
Sizing.Distribute,
|
||||
dropLocation
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doSetGroupActive(group: GroupPanel | undefined, skipFocus?: boolean): void {
|
||||
const isGroupAlreadyFocused = this._activeGroup === group;
|
||||
super.doSetGroupActive(group, skipFocus);
|
||||
|
@ -704,7 +704,9 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
|
||||
if (data) {
|
||||
if (data.panelId === null) {
|
||||
// this is a group move dnd event
|
||||
const { groupId } = data;
|
||||
|
||||
this._onMove.fire({
|
||||
target: position,
|
||||
groupId: groupId,
|
||||
|
@ -1,73 +1,13 @@
|
||||
import { last } from '../../array';
|
||||
import { DragHandler } from '../../dnd/abstractDragHandler';
|
||||
import {
|
||||
getPanelData,
|
||||
LocalSelectionTransfer,
|
||||
PanelTransfer,
|
||||
} from '../../dnd/dataTransfer';
|
||||
import { getPanelData } from '../../dnd/dataTransfer';
|
||||
import { Droptarget, DroptargetEvent } from '../../dnd/droptarget';
|
||||
import { addGhostImage } from '../../dnd/ghost';
|
||||
import { GroupDragHandler } from '../../dnd/groupDragHandler';
|
||||
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
||||
import { addDisposableListener, Emitter, Event } from '../../events';
|
||||
import { CompositeDisposable, IDisposable } from '../../lifecycle';
|
||||
import { CompositeDisposable } from '../../lifecycle';
|
||||
import { DockviewDropTargets } from '../dnd';
|
||||
import { GroupPanel } from '../groupviewPanel';
|
||||
|
||||
class CustomDragHandler extends DragHandler {
|
||||
private readonly panelTransfer =
|
||||
LocalSelectionTransfer.getInstance<PanelTransfer>();
|
||||
|
||||
constructor(
|
||||
element: HTMLElement,
|
||||
private readonly accessorId: string,
|
||||
private readonly group: GroupPanel
|
||||
) {
|
||||
super(element);
|
||||
}
|
||||
|
||||
getData(dataTransfer: DataTransfer | null): IDisposable {
|
||||
this.panelTransfer.setData(
|
||||
[new PanelTransfer(this.accessorId, this.group.id, null)],
|
||||
PanelTransfer.prototype
|
||||
);
|
||||
|
||||
const style = window.getComputedStyle(this.el);
|
||||
|
||||
const bgColor = style.getPropertyValue(
|
||||
'--dv-activegroup-visiblepanel-tab-background-color'
|
||||
);
|
||||
const color = style.getPropertyValue(
|
||||
'--dv-activegroup-visiblepanel-tab-color'
|
||||
);
|
||||
|
||||
if (dataTransfer) {
|
||||
const ghostElement = document.createElement('div');
|
||||
|
||||
ghostElement.style.backgroundColor = bgColor;
|
||||
ghostElement.style.color = color;
|
||||
ghostElement.style.padding = '2px 8px';
|
||||
ghostElement.style.height = '24px';
|
||||
ghostElement.style.fontSize = '11px';
|
||||
ghostElement.style.lineHeight = '20px';
|
||||
ghostElement.style.borderRadius = '12px';
|
||||
ghostElement.style.position = 'absolute';
|
||||
ghostElement.textContent = `Multiple Panels (${this.group.size})`;
|
||||
|
||||
addGhostImage(dataTransfer, ghostElement);
|
||||
}
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this.panelTransfer.clearData(PanelTransfer.prototype);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
export class VoidContainer extends CompositeDisposable {
|
||||
private readonly _element: HTMLElement;
|
||||
private readonly voidDropTarget: Droptarget;
|
||||
@ -98,11 +38,7 @@ export class VoidContainer extends CompositeDisposable {
|
||||
})
|
||||
);
|
||||
|
||||
const handler = new CustomDragHandler(
|
||||
this._element,
|
||||
accessor.id,
|
||||
group
|
||||
);
|
||||
const handler = new GroupDragHandler(this._element, accessor.id, group);
|
||||
|
||||
this.voidDropTarget = new Droptarget(this._element, {
|
||||
acceptedTargetZones: ['center'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user