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:
mathuo 2023-02-12 20:46:43 +07:00
commit 78336d6d90
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
9 changed files with 119 additions and 126 deletions

View File

@ -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();
});

View File

@ -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);

View File

@ -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);

View 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 {
//
}
}

View File

@ -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);
}

View File

@ -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
);

View File

@ -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);

View File

@ -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,

View File

@ -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'],