mirror of
https://github.com/mathuo/dockview
synced 2025-08-12 04:06:02 +00:00
feat: dnd to edge of dockview
This commit is contained in:
parent
5e4d2cb506
commit
f5709549c6
@ -17,6 +17,8 @@ export class DragAndDropObserver extends CompositeDisposable {
|
||||
// repeadedly.
|
||||
private counter = 0;
|
||||
|
||||
private target: any;
|
||||
|
||||
constructor(
|
||||
private element: HTMLElement,
|
||||
private callbacks: IDragAndDropObserverCallbacks
|
||||
@ -28,29 +30,55 @@ export class DragAndDropObserver extends CompositeDisposable {
|
||||
|
||||
private registerListeners(): void {
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.element, 'dragenter', (e: DragEvent) => {
|
||||
this.counter++;
|
||||
addDisposableListener(
|
||||
this.element,
|
||||
'dragenter',
|
||||
(e: DragEvent) => {
|
||||
this.counter++;
|
||||
|
||||
this.callbacks.onDragEnter(e);
|
||||
})
|
||||
try {
|
||||
this.target = e.target;
|
||||
this.callbacks.onDragEnter(e);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.element, 'dragover', (e: DragEvent) => {
|
||||
e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
|
||||
addDisposableListener(
|
||||
this.element,
|
||||
'dragover',
|
||||
(e: DragEvent) => {
|
||||
e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
|
||||
|
||||
if (this.callbacks.onDragOver) {
|
||||
this.callbacks.onDragOver(e);
|
||||
}
|
||||
})
|
||||
if (this.callbacks.onDragOver) {
|
||||
try {
|
||||
this.callbacks.onDragOver(e);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.element, 'dragleave', (e: DragEvent) => {
|
||||
this.counter--;
|
||||
console.log('dragleave');
|
||||
|
||||
if (this.counter === 0) {
|
||||
this.callbacks.onDragLeave(e);
|
||||
// if (this.counter === 0) {
|
||||
if (this.target === e.target) {
|
||||
this.target = null;
|
||||
try {
|
||||
this.callbacks.onDragLeave(e);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
@ -58,14 +86,23 @@ export class DragAndDropObserver extends CompositeDisposable {
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.element, 'dragend', (e: DragEvent) => {
|
||||
this.counter = 0;
|
||||
this.callbacks.onDragEnd(e);
|
||||
this.target = null;
|
||||
try {
|
||||
this.callbacks.onDragEnd(e);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.element, 'drop', (e: DragEvent) => {
|
||||
this.counter = 0;
|
||||
this.callbacks.onDrop(e);
|
||||
try {
|
||||
this.callbacks.onDrop(e);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
pointer-events: none;
|
||||
|
||||
&.left {
|
||||
transform: translateX(-25%) scaleX(0.5)
|
||||
transform: translateX(-35%) scaleX(0.3)
|
||||
}
|
||||
|
||||
&.right {
|
||||
|
@ -2,6 +2,7 @@ import { toggleClass } from '../dom';
|
||||
import { Emitter, Event } from '../events';
|
||||
import { CompositeDisposable } from '../lifecycle';
|
||||
import { DragAndDropObserver } from './dnd';
|
||||
import { clamp } from '../math';
|
||||
|
||||
export enum Position {
|
||||
Top = 'Top',
|
||||
@ -18,7 +19,12 @@ export interface DroptargetEvent {
|
||||
nativeEvent: DragEvent;
|
||||
}
|
||||
|
||||
export type DropTargetDirections = 'vertical' | 'horizontal' | 'all' | 'none';
|
||||
export type DropTargetDirections =
|
||||
| 'top'
|
||||
| 'bottom'
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'center';
|
||||
|
||||
function isBooleanValue(
|
||||
canDisplayOverlay: CanDisplayOverlay
|
||||
@ -42,19 +48,17 @@ export class Droptarget extends CompositeDisposable {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
set validOverlays(value: DropTargetDirections) {
|
||||
this.options.validOverlays = value;
|
||||
}
|
||||
|
||||
set canDisplayOverlay(value: CanDisplayOverlay) {
|
||||
this.options.canDisplayOverlay = value;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly element: HTMLElement,
|
||||
private readonly options: {
|
||||
canDisplayOverlay: CanDisplayOverlay;
|
||||
validOverlays: DropTargetDirections;
|
||||
acceptedTargetZones: DropTargetDirections[];
|
||||
overlayModel?: {
|
||||
units?: 'pixels' | 'percentage';
|
||||
type?: 'modal' | 'line';
|
||||
cover?: number;
|
||||
directionalThreshold?: number;
|
||||
};
|
||||
}
|
||||
) {
|
||||
super();
|
||||
@ -71,17 +75,25 @@ export class Droptarget extends CompositeDisposable {
|
||||
return; // avoid div!0
|
||||
}
|
||||
|
||||
const x = e.offsetX;
|
||||
const y = e.offsetY;
|
||||
const xp = (100 * x) / width;
|
||||
const yp = (100 * y) / height;
|
||||
const rect = (
|
||||
e.currentTarget as HTMLElement
|
||||
).getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
|
||||
const quadrant = this.calculateQuadrant(
|
||||
this.options.validOverlays,
|
||||
xp,
|
||||
yp
|
||||
this.options.acceptedTargetZones,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
);
|
||||
|
||||
if (quadrant === undefined) {
|
||||
this.removeDropTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBooleanValue(this.options.canDisplayOverlay)) {
|
||||
if (!this.options.canDisplayOverlay) {
|
||||
return;
|
||||
@ -102,7 +114,7 @@ export class Droptarget extends CompositeDisposable {
|
||||
this.element.append(this.target);
|
||||
}
|
||||
|
||||
if (this.options.validOverlays === 'none') {
|
||||
if (this.options.acceptedTargetZones.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,8 +122,12 @@ export class Droptarget extends CompositeDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const isSmallX = width < 100;
|
||||
const isSmallY = height < 100;
|
||||
const isSmallX =
|
||||
this.options.overlayModel?.type === 'line' ||
|
||||
width < 100;
|
||||
const isSmallY =
|
||||
this.options.overlayModel?.type === 'line' ||
|
||||
height < 100;
|
||||
|
||||
this.toggleClasses(quadrant, isSmallX, isSmallY);
|
||||
|
||||
@ -157,10 +173,39 @@ export class Droptarget extends CompositeDisposable {
|
||||
const isTop = quadrant === 'top';
|
||||
const isBottom = quadrant === 'bottom';
|
||||
|
||||
toggleClass(this.overlay, 'right', !isSmallX && isRight);
|
||||
toggleClass(this.overlay, 'left', !isSmallX && isLeft);
|
||||
toggleClass(this.overlay, 'top', !isSmallY && isTop);
|
||||
toggleClass(this.overlay, 'bottom', !isSmallY && isBottom);
|
||||
const size =
|
||||
typeof this.options.overlayModel?.cover === 'number'
|
||||
? clamp(this.options.overlayModel?.cover, 0, 1)
|
||||
: 0.5;
|
||||
|
||||
const translate = (1 - size) / 2;
|
||||
const scale = size;
|
||||
|
||||
let transform = '';
|
||||
|
||||
const rightClass = !isSmallX && isRight;
|
||||
const leftClass = !isSmallX && isLeft;
|
||||
const topClass = !isSmallY && isTop;
|
||||
const bottomClass = !isSmallY && isBottom;
|
||||
|
||||
if (rightClass) {
|
||||
transform = `translateX(${100 * translate}%) scaleX(${scale})`;
|
||||
} else if (leftClass) {
|
||||
transform = `translateX(-${100 * translate}%) scaleX(${scale})`;
|
||||
} else if (topClass) {
|
||||
transform = `translateY(-${100 * translate}%) scaleY(${scale})`;
|
||||
} else if (bottomClass) {
|
||||
transform = `translateY(${100 * translate}%) scaleY(${scale})`;
|
||||
} else {
|
||||
transform = '';
|
||||
}
|
||||
|
||||
this.overlay.style.transform = transform;
|
||||
|
||||
// toggleClass(this.overlay, 'right', !isSmallX && isRight);
|
||||
// toggleClass(this.overlay, 'left', !isSmallX && isLeft);
|
||||
// toggleClass(this.overlay, 'top', !isSmallY && isTop);
|
||||
// toggleClass(this.overlay, 'bottom', !isSmallY && isBottom);
|
||||
|
||||
toggleClass(this.overlay, 'small-right', isSmallX && isRight);
|
||||
toggleClass(this.overlay, 'small-left', isSmallX && isLeft);
|
||||
@ -189,47 +234,167 @@ export class Droptarget extends CompositeDisposable {
|
||||
}
|
||||
|
||||
private calculateQuadrant(
|
||||
overlayType: DropTargetDirections,
|
||||
xp: number,
|
||||
yp: number
|
||||
): Quadrant | null {
|
||||
switch (overlayType) {
|
||||
case 'all':
|
||||
if (xp < 20) {
|
||||
return 'left';
|
||||
}
|
||||
if (xp > 80) {
|
||||
return 'right';
|
||||
}
|
||||
if (yp < 20) {
|
||||
return 'top';
|
||||
}
|
||||
if (yp > 80) {
|
||||
return 'bottom';
|
||||
}
|
||||
break;
|
||||
case 'vertical':
|
||||
if (yp < 50) {
|
||||
return 'top';
|
||||
}
|
||||
return 'bottom';
|
||||
|
||||
case 'horizontal':
|
||||
if (xp < 50) {
|
||||
return 'left';
|
||||
}
|
||||
return 'right';
|
||||
overlayType: DropTargetDirections[],
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number
|
||||
): Quadrant | null | undefined {
|
||||
if (
|
||||
!this.options.overlayModel?.units ||
|
||||
this.options.overlayModel?.units === 'percentage'
|
||||
) {
|
||||
return calculateQuadrant_Percentage(
|
||||
overlayType,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
typeof this.options.overlayModel?.directionalThreshold ===
|
||||
'number'
|
||||
? this.options.overlayModel?.directionalThreshold
|
||||
: 20
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
return calculateQuadrant_Pixels(
|
||||
overlayType,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
typeof this.options.overlayModel?.directionalThreshold === 'number'
|
||||
? this.options.overlayModel?.directionalThreshold
|
||||
: 20
|
||||
);
|
||||
}
|
||||
|
||||
private removeDropTarget() {
|
||||
console.log('remove');
|
||||
if (this.target) {
|
||||
this._state = undefined;
|
||||
this.element.removeChild(this.target);
|
||||
this.target = undefined;
|
||||
this.overlay = undefined;
|
||||
this.element.classList.remove('drop-target');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calculateQuadrant_Percentage(
|
||||
overlayType: DropTargetDirections[],
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
threshold: number
|
||||
): Quadrant | null | undefined {
|
||||
const xp = (100 * x) / width;
|
||||
const yp = (100 * y) / height;
|
||||
|
||||
if (overlayType.includes('left') && xp < threshold) {
|
||||
return 'left';
|
||||
}
|
||||
if (overlayType.includes('right') && xp > 100 - threshold) {
|
||||
return 'right';
|
||||
}
|
||||
if (overlayType.includes('top') && yp < threshold) {
|
||||
return 'top';
|
||||
}
|
||||
if (overlayType.includes('bottom') && yp > 100 - threshold) {
|
||||
return 'bottom';
|
||||
}
|
||||
|
||||
// switch (overlayType) {
|
||||
// case 'all':
|
||||
// case 'nocenter':
|
||||
// if (xp < threshold) {
|
||||
// return 'left';
|
||||
// }
|
||||
// if (xp > 100 - threshold) {
|
||||
// return 'right';
|
||||
// }
|
||||
// if (yp < threshold) {
|
||||
// return 'top';
|
||||
// }
|
||||
// if (yp > 100 - threshold) {
|
||||
// return 'bottom';
|
||||
// }
|
||||
|
||||
// break;
|
||||
// case 'vertical':
|
||||
// if (yp < 50) {
|
||||
// return 'top';
|
||||
// }
|
||||
// return 'bottom';
|
||||
|
||||
// case 'horizontal':
|
||||
// if (xp < 50) {
|
||||
// return 'left';
|
||||
// }
|
||||
// return 'right';
|
||||
// }
|
||||
|
||||
if (!overlayType.includes('center')) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function calculateQuadrant_Pixels(
|
||||
overlayType: DropTargetDirections[],
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
threshold: number
|
||||
): Quadrant | null | undefined {
|
||||
if (overlayType.includes('left') && x < threshold) {
|
||||
return 'left';
|
||||
}
|
||||
if (overlayType.includes('right') && x > width - threshold) {
|
||||
return 'right';
|
||||
}
|
||||
if (overlayType.includes('top') && y < threshold) {
|
||||
return 'top';
|
||||
}
|
||||
if (overlayType.includes('right') && y > height - threshold) {
|
||||
return 'bottom';
|
||||
}
|
||||
|
||||
// switch (overlayType) {
|
||||
// case 'all':
|
||||
// case 'nocenter':
|
||||
// if (x < threshold) {
|
||||
// return 'left';
|
||||
// }
|
||||
// if (x > width - threshold) {
|
||||
// return 'right';
|
||||
// }
|
||||
// if (y < threshold) {
|
||||
// return 'top';
|
||||
// }
|
||||
// if (y > height - threshold) {
|
||||
// return 'bottom';
|
||||
// }
|
||||
|
||||
// break;
|
||||
// case 'vertical':
|
||||
// if (x < width / 2) {
|
||||
// return 'top';
|
||||
// }
|
||||
// return 'bottom';
|
||||
// case 'horizontal':
|
||||
// if (y < height / 2) {
|
||||
// return 'left';
|
||||
// }
|
||||
// return 'right';
|
||||
// }
|
||||
|
||||
if (!overlayType.includes('center')) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -3,8 +3,9 @@ import {
|
||||
SerializedGridObject,
|
||||
getGridLocation,
|
||||
ISerializedLeafNode,
|
||||
orthogonal,
|
||||
} from '../gridview/gridview';
|
||||
import { Position } from '../dnd/droptarget';
|
||||
import { Droptarget, Position } from '../dnd/droptarget';
|
||||
import { tail, sequenceEquals } from '../array';
|
||||
import { GroupviewPanelState, IDockviewPanel } from '../groupview/groupPanel';
|
||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||
@ -40,6 +41,7 @@ import {
|
||||
} from '../groupview/groupview';
|
||||
import { GroupPanel } from '../groupview/groupviewPanel';
|
||||
import { DefaultGroupPanelView } from './defaultGroupPanelView';
|
||||
import { getPanelData } from '../dnd/dataTransfer';
|
||||
|
||||
const nextGroupId = sequentialNumberGenerator();
|
||||
|
||||
@ -224,6 +226,59 @@ export class DockviewComponent
|
||||
this.options.watermarkComponent = Watermark;
|
||||
}
|
||||
|
||||
|
||||
const dropTarget = new Droptarget(this.element, {
|
||||
canDisplayOverlay:() => {
|
||||
return true
|
||||
},
|
||||
acceptedTargetZones: ['top', 'bottom', 'left', 'right'],
|
||||
overlayModel:{
|
||||
units: 'pixels',
|
||||
type: 'line',
|
||||
directionalThreshold: 5,
|
||||
cover: 0.1
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
this.addDisposables(
|
||||
dropTarget,
|
||||
dropTarget.onDrop((event) => {
|
||||
const data = getPanelData();
|
||||
|
||||
if(!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(event.position) {
|
||||
case Position.Top:
|
||||
case Position.Bottom:
|
||||
if(this.gridview.orientation === Orientation.HORIZONTAL) {
|
||||
this.gridview.flipOrientation();
|
||||
}
|
||||
break;
|
||||
case Position.Left:
|
||||
case Position.Right:
|
||||
if(this.gridview.orientation === Orientation.VERTICAL) {
|
||||
this.gridview.flipOrientation();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
switch(event.position) {
|
||||
case Position.Top:
|
||||
case Position.Left:
|
||||
this.createGroupAtLocation([0]);
|
||||
break;
|
||||
case Position.Bottom:
|
||||
case Position.Right:
|
||||
this.createGroupAtLocation([this.gridview.length]);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
this._api = new DockviewApi(this);
|
||||
}
|
||||
|
||||
@ -462,6 +517,11 @@ export class DockviewComponent
|
||||
}
|
||||
} else {
|
||||
const group = this.createGroupAtLocation();
|
||||
|
||||
if(options.type === 'singular') {
|
||||
group.locked = true;
|
||||
}
|
||||
|
||||
panel = this.createPanel(options, group);
|
||||
group.model.openPanel(panel);
|
||||
}
|
||||
@ -575,8 +635,6 @@ export class DockviewComponent
|
||||
|
||||
|
||||
if(itemId === undefined) {
|
||||
|
||||
|
||||
if(sourceGroup) {
|
||||
if (!target || target === Position.Center) {
|
||||
const activePanel = sourceGroup.activePanel;
|
||||
|
@ -38,7 +38,7 @@ export class DockviewGroupPanel
|
||||
return this._group;
|
||||
}
|
||||
|
||||
get view() {
|
||||
get view(): IGroupPanelView | undefined {
|
||||
return this._view;
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ export interface AddPanelOptions
|
||||
direction?: Direction;
|
||||
referencePanel?: string;
|
||||
};
|
||||
type?: 'tabular' | 'singular';
|
||||
}
|
||||
|
||||
export interface AddGroupOptions {
|
||||
|
@ -276,6 +276,10 @@ export class Gridview implements IDisposable {
|
||||
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
|
||||
this._onDidChange.event;
|
||||
|
||||
public get length(): number {
|
||||
return this._root ? this._root.children.length : 0;
|
||||
}
|
||||
|
||||
public serialize() {
|
||||
const root = serializeBranchNode(this.getView(), this.orientation);
|
||||
|
||||
@ -410,6 +414,35 @@ export class Gridview implements IDisposable {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If the root is orientated as a VERTICAL node then nest the existing root within a new HORIZIONTAL root node
|
||||
* If the root is orientated as a HORIZONTAL node then nest the existing root within a new VERITCAL root node
|
||||
*/
|
||||
public flipOrientation(): void {
|
||||
if (!this._root) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldRoot = this.root;
|
||||
oldRoot.element.remove();
|
||||
|
||||
this._root = new BranchNode(
|
||||
orthogonal(oldRoot.orientation),
|
||||
this.proportionalLayout,
|
||||
this.styles,
|
||||
this.root.orthogonalSize,
|
||||
this.root.size
|
||||
);
|
||||
|
||||
this._root.addChild(oldRoot, Sizing.Distribute, 0);
|
||||
|
||||
this.element.appendChild(this._root.element);
|
||||
|
||||
this.disposable.value = this._root.onDidChange((e) => {
|
||||
this._onDidChange.fire(e);
|
||||
});
|
||||
}
|
||||
|
||||
public next(location: number[]) {
|
||||
return this.progmaticSelect(location);
|
||||
}
|
||||
|
@ -167,6 +167,8 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
|
||||
set locked(value: boolean) {
|
||||
this._locked = value;
|
||||
|
||||
toggleClass(this.container, 'locked-groupview', value);
|
||||
}
|
||||
|
||||
get isActive(): boolean {
|
||||
@ -226,20 +228,20 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
private accessor: DockviewComponent,
|
||||
public id: string,
|
||||
private readonly options: GroupOptions,
|
||||
private readonly parent: GroupPanel
|
||||
private readonly groupPanel: GroupPanel
|
||||
) {
|
||||
super();
|
||||
|
||||
this.container.classList.add('groupview');
|
||||
|
||||
this.tabsContainer = new TabsContainer(this.accessor, this.parent, {
|
||||
this.tabsContainer = new TabsContainer(this.accessor, this.groupPanel, {
|
||||
tabHeight: options.tabHeight,
|
||||
});
|
||||
|
||||
this.contentContainer = new ContentContainer();
|
||||
|
||||
this.dropTarget = new Droptarget(this.contentContainer.element, {
|
||||
validOverlays: 'all',
|
||||
acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
|
||||
canDisplayOverlay: (event, quadrant) => {
|
||||
if (this.locked && !quadrant) {
|
||||
return false;
|
||||
@ -287,7 +289,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
this.handleDropEvent(event.event, Position.Center, event.index);
|
||||
}),
|
||||
this.contentContainer.onDidFocus(() => {
|
||||
this.accessor.doSetGroupActive(this.parent, true);
|
||||
this.accessor.doSetGroupActive(this.groupPanel, true);
|
||||
}),
|
||||
this.contentContainer.onDidBlur(() => {
|
||||
// noop
|
||||
@ -316,12 +318,12 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
|
||||
if (this.accessor.options.createGroupControlElement) {
|
||||
this._control = this.accessor.options.createGroupControlElement(
|
||||
this.parent
|
||||
this.groupPanel
|
||||
);
|
||||
this.addDisposables(this._control);
|
||||
this._control.init({
|
||||
containerApi: new DockviewApi(this.accessor),
|
||||
api: this.parent.api,
|
||||
api: this.groupPanel.api,
|
||||
});
|
||||
this.tabsContainer.setActionElement(this._control.element);
|
||||
}
|
||||
@ -441,11 +443,11 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
const skipSetGroupActive = !!options.skipSetGroupActive;
|
||||
|
||||
// ensure the group is updated before we fire any events
|
||||
panel.updateParentGroup(this.parent, true);
|
||||
panel.updateParentGroup(this.groupPanel, true);
|
||||
|
||||
if (this._activePanel === panel) {
|
||||
if (!skipSetGroupActive) {
|
||||
this.accessor.doSetGroupActive(this.parent);
|
||||
this.accessor.doSetGroupActive(this.groupPanel);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -457,7 +459,10 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
}
|
||||
|
||||
if (!skipSetGroupActive) {
|
||||
this.accessor.doSetGroupActive(this.parent, !!options.skipFocus);
|
||||
this.accessor.doSetGroupActive(
|
||||
this.groupPanel,
|
||||
!!options.skipFocus
|
||||
);
|
||||
}
|
||||
|
||||
this.updateContainer();
|
||||
@ -486,7 +491,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
this.doClose(panel);
|
||||
}
|
||||
} else {
|
||||
this.accessor.removeGroup(this.parent);
|
||||
this.accessor.removeGroup(this.groupPanel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -643,7 +648,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
toggleClass(this.container, 'empty', this.isEmpty);
|
||||
|
||||
this.panels.forEach((panel) =>
|
||||
panel.updateParentGroup(this.parent, this.isActive)
|
||||
panel.updateParentGroup(this.groupPanel, this.isActive)
|
||||
);
|
||||
|
||||
if (this.isEmpty && !this.watermark) {
|
||||
@ -658,7 +663,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
|
||||
addDisposableListener(this.watermark.element, 'click', () => {
|
||||
if (!this.isActive) {
|
||||
this.accessor.doSetGroupActive(this.parent);
|
||||
this.accessor.doSetGroupActive(this.groupPanel);
|
||||
}
|
||||
});
|
||||
|
||||
@ -666,7 +671,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
this.tabsContainer.hide();
|
||||
this.container.appendChild(this.watermark.element);
|
||||
|
||||
this.watermark.updateParentGroup(this.parent, true);
|
||||
this.watermark.updateParentGroup(this.groupPanel, true);
|
||||
}
|
||||
if (!this.isEmpty && this.watermark) {
|
||||
this.watermark.element.remove();
|
||||
|
@ -109,7 +109,7 @@ export class Tab extends CompositeDisposable implements ITab {
|
||||
);
|
||||
|
||||
this.droptarget = new Droptarget(this._element, {
|
||||
validOverlays: 'none',
|
||||
acceptedTargetZones: ['center'],
|
||||
canDisplayOverlay: (event) => {
|
||||
const data = getPanelData();
|
||||
if (data && this.accessor.id === data.viewId) {
|
||||
|
@ -10,6 +10,22 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.single-panel {
|
||||
background-color: red !important;
|
||||
|
||||
.tabs-container {
|
||||
flex-grow: 1;
|
||||
|
||||
.tab {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.void-container {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.void-container {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
|
@ -9,6 +9,7 @@ import { IDockviewPanel } from '../groupPanel';
|
||||
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
||||
import { GroupPanel } from '../groupviewPanel';
|
||||
import { VoidContainer } from './voidContainer';
|
||||
import { toggleClass } from '../../dom';
|
||||
|
||||
export interface TabDropIndexEvent {
|
||||
event: DragEvent;
|
||||
@ -146,6 +147,19 @@ export class TabsContainer
|
||||
|
||||
this.height = options.tabHeight;
|
||||
|
||||
this.addDisposables(
|
||||
this.accessor.onDidAddPanel((e) => {
|
||||
if (e.api.group === this.group) {
|
||||
toggleClass(this._element, 'single-panel', this.size === 1);
|
||||
}
|
||||
}),
|
||||
this.accessor.onDidRemovePanel((e) => {
|
||||
if (e.api.group === this.group) {
|
||||
toggleClass(this._element, 'single-panel', this.size === 1);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.actionContainer = document.createElement('div');
|
||||
this.actionContainer.className = 'action-container';
|
||||
|
||||
|
@ -105,7 +105,7 @@ export class VoidContainer extends CompositeDisposable {
|
||||
);
|
||||
|
||||
this.voidDropTarget = new Droptarget(this._element, {
|
||||
validOverlays: 'none',
|
||||
acceptedTargetZones: ['center'],
|
||||
canDisplayOverlay: (event) => {
|
||||
const data = getPanelData();
|
||||
|
||||
|
@ -70,7 +70,8 @@ export abstract class DraggablePaneviewPanel extends PaneviewPanel {
|
||||
})(this.header);
|
||||
|
||||
this.target = new Droptarget(this.element, {
|
||||
validOverlays: 'vertical',
|
||||
acceptedTargetZones: ['top', 'bottom'],
|
||||
threshold: 50,
|
||||
canDisplayOverlay: (event) => {
|
||||
const data = getPaneData();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user