feat: dockview custom dnd events

- remove old flag for external dnd events
- add methods onDidDrop and showDndOverlay to allow interaction with
  custom dnd events
This commit is contained in:
mathuo 2022-02-22 21:57:06 +00:00
parent 0b05115733
commit c9eb954de8
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
6 changed files with 73 additions and 15 deletions

View File

@ -410,9 +410,14 @@ export const TestGrid = (props: IGridviewPanelProps) => {
components={components}
tabComponents={tabComponents}
debug={false}
enableExternalDragEvents={true}
onTabContextMenu={onTabContextMenu}
watermarkComponent={Watermark}
showDndOverlay={(ev, target) => {
return true;
}}
onDidDrop={(ev) => {
console.log('onDidDrop', ev);
}}
/>
</>
);

View File

@ -207,9 +207,7 @@ describe('groupview', () => {
beforeEach(() => {
dockview = <IDockviewComponent>(<any>{
options: {
enableExternalDragEvents: false,
},
options: {},
createWatermarkComponent: () => new Watermark(),
doSetGroupActive: jest.fn(),
id: 'dockview-1',

View File

@ -41,6 +41,7 @@ import {
GroupChangeKind2,
GroupOptions,
GroupPanelViewState,
GroupviewDropEvent,
} from '../groupview/groupview';
import { GroupviewPanel } from '../groupview/groupviewPanel';
import { DefaultGroupPanelView } from './defaultGroupPanelView';
@ -71,12 +72,18 @@ export type DockviewComponentUpdateOptions = Pick<
| 'frameworkComponents'
| 'tabComponents'
| 'frameworkTabComponents'
| 'showDndOverlay'
>;
export interface DockviewDropEvent extends GroupviewDropEvent {
api: DockviewApi;
}
export interface IDockviewComponent extends IBaseGrid<GroupviewPanel> {
readonly activePanel: IGroupPanel | undefined;
readonly totalPanels: number;
readonly panels: IGroupPanel[];
readonly onDidDrop: Event<DockviewDropEvent>;
tabHeight: number | undefined;
deserializer: IPanelDeserializer | undefined;
updateOptions(options: DockviewComponentUpdateOptions): void;
@ -124,9 +131,14 @@ export class DockviewComponent
private readonly _onTabInteractionEvent = new Emitter<LayoutMouseEvent>();
readonly onTabInteractionEvent: Event<LayoutMouseEvent> =
this._onTabInteractionEvent.event;
private readonly _onTabContextMenu = new Emitter<TabContextMenuEvent>();
readonly onTabContextMenu: Event<TabContextMenuEvent> =
this._onTabContextMenu.event;
private readonly _onDidDrop = new Emitter<DockviewDropEvent>();
readonly onDidDrop: Event<DockviewDropEvent> = this._onDidDrop.event;
// everything else
private _deserializer: IPanelDeserializer | undefined;
private panelState: State = {};
@ -668,6 +680,9 @@ export class DockviewComponent
const { groupId, itemId, target, index } = event;
this.moveGroupOrPanel(view, groupId, itemId, target, index);
}),
view.model.onDidDrop((event) => {
this._onDidDrop.fire({ ...event, api: this._api });
}),
view.model.onDidGroupChange((event) => {
switch (event.kind) {
case GroupChangeKind2.ADD_PANEL:
@ -716,6 +731,9 @@ export class DockviewComponent
super.dispose();
this._onGridEvent.dispose();
this._onDidDrop.dispose();
this._onTabContextMenu.dispose();
this._onTabInteractionEvent.dispose();
}
/**

View File

@ -11,6 +11,7 @@ import {
import { GroupviewPanel } from '../groupview/groupviewPanel';
import { ISplitviewStyles, Orientation } from '../splitview/core/splitview';
import { FrameworkFactory } from '../types';
import { DockviewDropTargets } from '../groupview/dnd';
export interface GroupPanelFrameworkComponentFactory {
content: FrameworkFactory<IContentRenderer>;
@ -54,9 +55,9 @@ export interface DockviewOptions extends DockviewRenderFunctions {
frameworkComponentFactory?: GroupPanelFrameworkComponentFactory;
tabHeight?: number;
debug?: boolean;
enableExternalDragEvents?: boolean;
orientation?: Orientation;
styles?: ISplitviewStyles;
showDndOverlay?: (event: DragEvent, target: DockviewDropTargets) => boolean;
}
export interface PanelOptions {

View File

@ -67,14 +67,21 @@ export interface GroupPanelViewState {
id: string;
}
export interface GroupviewDropEvent {
nativeEvent: DragEvent;
position: Position;
index?: number;
}
export interface IGroupview extends IDisposable, IGridPanelView {
readonly isActive: boolean;
readonly size: number;
readonly panels: IGroupPanel[];
readonly tabHeight: number | undefined;
readonly activePanel: IGroupPanel | undefined;
readonly onDidDrop: Event<GroupviewDropEvent>;
// state
isPanelActive: (panel: IGroupPanel) => boolean;
activePanel: IGroupPanel | undefined;
indexOf(panel: IGroupPanel): number;
// panel lifecycle
openPanel(
@ -124,6 +131,9 @@ export class Groupview extends CompositeDisposable implements IGroupview {
readonly onDidGroupChange: Event<GroupviewChangeEvent> =
this._onDidGroupChange.event;
private readonly _onDidDrop = new Emitter<GroupviewDropEvent>();
readonly onDidDrop: Event<GroupviewDropEvent> = this._onDidDrop.event;
get element(): HTMLElement {
throw new Error('not supported');
}
@ -184,7 +194,12 @@ export class Groupview extends CompositeDisposable implements IGroupview {
this.container.classList.add('groupview');
this.addDisposables(this._onMove, this._onDidGroupChange);
this.addDisposables(
this._onMove,
this._onDidGroupChange,
this._onDidChange,
this._onDidDrop
);
this.tabsContainer = new TabsContainer(this.accessor, this.parent, {
tabHeight: options.tabHeight,
@ -619,11 +634,11 @@ export class Groupview extends CompositeDisposable implements IGroupview {
}
}
canDisplayOverlay(
dragOverEvent: DragEvent,
target: DockviewDropTargets
): boolean {
canDisplayOverlay(event: DragEvent, target: DockviewDropTargets): boolean {
// custom overlay handler
if (this.accessor.options.showDndOverlay) {
return this.accessor.options.showDndOverlay(event, target);
}
return false;
}
@ -658,7 +673,8 @@ export class Groupview extends CompositeDisposable implements IGroupview {
index,
});
} else {
// custom drop handler
// TODO: custom drop handler
this._onDidDrop.fire({ nativeEvent: event, position, index });
}
}

View File

@ -1,5 +1,8 @@
import * as React from 'react';
import { DockviewComponent } from '../../dockview/dockviewComponent';
import {
DockviewComponent,
DockviewDropEvent,
} from '../../dockview/dockviewComponent';
import { ReactPanelContentPart } from './reactContentPart';
import { ReactPanelHeaderPart } from './reactHeaderPart';
import { ReactPanelDeserialzier } from '../deserializer';
@ -14,6 +17,7 @@ import { ReactWatermarkPart } from './reactWatermarkPart';
import { PanelCollection, PanelParameters } from '../types';
import { watchElementResize } from '../../dom';
import { IContentRenderer, ITabRenderer } from '../../groupview/types';
import { DockviewDropTargets } from '../../groupview/dnd';
export interface IGroupPanelBaseProps<T extends {} = Record<string, any>>
extends PanelParameters<T> {
@ -43,8 +47,9 @@ export interface IDockviewReactProps {
onReady?: (event: DockviewReadyEvent) => void;
debug?: boolean;
tabHeight?: number;
enableExternalDragEvents?: boolean;
onTabContextMenu?: (event: TabContextMenuEvent) => void;
onDidDrop?: (event: DockviewDropEvent) => void;
showDndOverlay?: (event: DragEvent, target: DockviewDropTargets) => boolean;
hideBorders?: boolean;
className?: string;
disableAutoResizing?: boolean;
@ -128,13 +133,18 @@ export const DockviewReact = React.forwardRef(
frameworkTabComponents: props.tabComponents,
tabHeight: props.tabHeight,
debug: props.debug,
enableExternalDragEvents: props.enableExternalDragEvents,
watermarkFrameworkComponent: props.watermarkComponent,
styles: props.hideBorders
? { separatorBorder: 'transparent' }
: undefined,
});
const disposable = dockview.onDidDrop((event) => {
if (props.onDidDrop) {
props.onDidDrop(event);
}
});
domRef.current?.appendChild(dockview.element);
dockview.deserializer = new ReactPanelDeserialzier(dockview);
@ -148,6 +158,7 @@ export const DockviewReact = React.forwardRef(
dockviewRef.current = dockview;
return () => {
disposable.dispose();
dockview.dispose();
};
}, []);
@ -161,6 +172,15 @@ export const DockviewReact = React.forwardRef(
});
}, [props.components]);
React.useEffect(() => {
if (!dockviewRef.current) {
return;
}
dockviewRef.current.updateOptions({
showDndOverlay: props.showDndOverlay,
});
}, [props.showDndOverlay]);
React.useEffect(() => {
if (!dockviewRef.current) {
return;