Skip to content

Commit

Permalink
Merge pull request #308 from mathuo/230-explore-floating-groups
Browse files Browse the repository at this point in the history
230 explore floating groups
  • Loading branch information
mathuo authored Jul 20, 2023
2 parents 1dd8392 + 8668697 commit 430f97f
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ describe('componentFactory', () => {

expect(component).toHaveBeenCalled();

expect(componentResult instanceof component);
expect(componentResult instanceof component).toBeTruthy();
});
});
});
124 changes: 74 additions & 50 deletions packages/dockview-core/src/dnd/overlay.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { quasiDefaultPrevented, toggleClass } from '../dom';
import {
getElementsByTagName,
quasiDefaultPrevented,
toggleClass,
} from '../dom';
import {
Emitter,
Event,
Expand Down Expand Up @@ -29,6 +33,9 @@ export class Overlay extends CompositeDisposable {
private readonly _onDidChange = new Emitter<void>();
readonly onDidChange: Event<void> = this._onDidChange.event;

private readonly _onDidChangeEnd = new Emitter<void>();
readonly onDidChangeEnd: Event<void> = this._onDidChangeEnd.event;

private static MINIMUM_HEIGHT = 20;
private static MINIMUM_WIDTH = 20;

Expand All @@ -46,9 +53,10 @@ export class Overlay extends CompositeDisposable {
) {
super();

this.addDisposables(this._onDidChange);
this.addDisposables(this._onDidChange, this._onDidChangeEnd);

this._element.className = 'dv-resize-container';

this.setupOverlay();
this.setupResize('top');
this.setupResize('bottom');
this.setupResize('left');
Expand All @@ -62,7 +70,12 @@ export class Overlay extends CompositeDisposable {
this.options.container.appendChild(this._element);

// if input bad resize within acceptable boundaries
this.renderWithinBoundaryConditions();
this.setBounds({
height: this.options.height,
width: this.options.width,
top: this.options.top,
left: this.options.left,
});
}

setBounds(
Expand All @@ -71,7 +84,7 @@ export class Overlay extends CompositeDisposable {
width: number;
top: number;
left: number;
}>
}> = {}
): void {
if (typeof bounds.height === 'number') {
this._element.style.height = `${bounds.height}px`;
Expand All @@ -86,25 +99,11 @@ export class Overlay extends CompositeDisposable {
this._element.style.left = `${bounds.left}px`;
}

this.renderWithinBoundaryConditions();
}

toJSON(): { top: number; left: number; height: number; width: number } {
const container = this.options.container.getBoundingClientRect();
const element = this._element.getBoundingClientRect();

return {
top: element.top - container.top,
left: element.left - container.left,
width: element.width,
height: element.height,
};
}

renderWithinBoundaryConditions(): void {
const containerRect = this.options.container.getBoundingClientRect();
const overlayRect = this._element.getBoundingClientRect();

// region: ensure bounds within allowable limits

// a minimum width of minimumViewportWidth must be inside the viewport
const xOffset = Math.max(
0,
Expand All @@ -131,6 +130,20 @@ export class Overlay extends CompositeDisposable {

this._element.style.left = `${left}px`;
this._element.style.top = `${top}px`;

this._onDidChange.fire();
}

toJSON(): { top: number; left: number; height: number; width: number } {
const container = this.options.container.getBoundingClientRect();
const element = this._element.getBoundingClientRect();

return {
top: element.top - container.top,
left: element.left - container.left,
width: element.width,
height: element.height,
};
}

setupDrag(
Expand All @@ -142,7 +155,23 @@ export class Overlay extends CompositeDisposable {
const track = () => {
let offset: { x: number; y: number } | null = null;

const iframes = [
...getElementsByTagName('iframe'),
...getElementsByTagName('webview'),
];

for (const iframe of iframes) {
iframe.style.pointerEvents = 'none';
}

move.value = new CompositeDisposable(
{
dispose: () => {
for (const iframe of iframes) {
iframe.style.pointerEvents = 'auto';
}
},
},
addDisposableWindowListener(window, 'mousemove', (e) => {
const containerRect =
this.options.container.getBoundingClientRect();
Expand Down Expand Up @@ -191,8 +220,7 @@ export class Overlay extends CompositeDisposable {
)
);

this._element.style.left = `${left}px`;
this._element.style.top = `${top}px`;
this.setBounds({ top, left });
}),
addDisposableWindowListener(window, 'mouseup', () => {
toggleClass(
Expand All @@ -202,7 +230,7 @@ export class Overlay extends CompositeDisposable {
);

move.dispose();
this._onDidChange.fire();
this._onDidChangeEnd.fire();
})
);
};
Expand Down Expand Up @@ -259,15 +287,6 @@ export class Overlay extends CompositeDisposable {
}
}

private setupOverlay(): void {
this._element.style.height = `${this.options.height}px`;
this._element.style.width = `${this.options.width}px`;
this._element.style.left = `${this.options.left}px`;
this._element.style.top = `${this.options.top}px`;

this._element.className = 'dv-resize-container';
}

private setupResize(
direction:
| 'top'
Expand Down Expand Up @@ -297,6 +316,15 @@ export class Overlay extends CompositeDisposable {
originalWidth: number;
} | null = null;

const iframes = [
...getElementsByTagName('iframe'),
...getElementsByTagName('webview'),
];

for (const iframe of iframes) {
iframe.style.pointerEvents = 'none';
}

move.value = new CompositeDisposable(
addDisposableWindowListener(window, 'mousemove', (e) => {
const containerRect =
Expand All @@ -317,10 +345,10 @@ export class Overlay extends CompositeDisposable {
};
}

let top: number | null = null;
let height: number | null = null;
let left: number | null = null;
let width: number | null = null;
let top: number | undefined = undefined;
let height: number | undefined = undefined;
let left: number | undefined = undefined;
let width: number | undefined = undefined;

const minimumInViewportHeight =
this.options.minimumInViewportHeight;
Expand Down Expand Up @@ -431,22 +459,18 @@ export class Overlay extends CompositeDisposable {
break;
}

if (height !== null) {
this._element.style.height = `${height}px`;
}
if (top !== null) {
this._element.style.top = `${top}px`;
}
if (left !== null) {
this._element.style.left = `${left}px`;
}
if (width !== null) {
this._element.style.width = `${width}px`;
}
this.setBounds({ height, width, top, left });
}),
{
dispose: () => {
for (const iframe of iframes) {
iframe.style.pointerEvents = 'auto';
}
},
},
addDisposableWindowListener(window, 'mouseup', () => {
move.dispose();
this._onDidChange.fire();
this._onDidChangeEnd.fire();
})
);
})
Expand Down
19 changes: 16 additions & 3 deletions packages/dockview-core/src/dockview/dockviewComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { DockviewGroupPanel } from './dockviewGroupPanel';
import { DockviewPanelModel } from './dockviewPanelModel';
import { getPanelData } from '../dnd/dataTransfer';
import { Overlay } from '../dnd/overlay';
import { toggleClass } from '../dom';
import { toggleClass, watchElementResize } from '../dom';
import {
DockviewFloatingGroupPanel,
IDockviewFloatingGroupPanel,
Expand Down Expand Up @@ -369,8 +369,19 @@ export class DockviewComponent
overlay
);

const disposable = watchElementResize(group.element, (entry) => {
const { width, height } = entry.contentRect;
group.layout(width, height); // let the group know it's size is changing so it can fire events to the panel
});

floatingGroupPanel.addDisposables(
overlay.onDidChange(() => {
// this is either a resize or a move
// to inform the panels .layout(...) the group with it's current size
// don't care about resize since the above watcher handles that
group.layout(group.height, group.width);
}),
overlay.onDidChangeEnd(() => {
this._bufferOnDidLayoutChange.fire();
}),
group.onDidChange((event) => {
Expand All @@ -381,6 +392,8 @@ export class DockviewComponent
}),
{
dispose: () => {
disposable.dispose();

group.model.isFloating = false;
remove(this.floatingGroups, floatingGroupPanel);
this.updateWatermark();
Expand Down Expand Up @@ -451,7 +464,7 @@ export class DockviewComponent
if (this.floatingGroups) {
for (const floating of this.floatingGroups) {
// ensure floting groups stay within visible boundaries
floating.overlay.renderWithinBoundaryConditions();
floating.overlay.setBounds();
}
}
}
Expand Down Expand Up @@ -621,7 +634,7 @@ export class DockviewComponent
}

for (const floatingGroup of this.floatingGroups) {
floatingGroup.overlay.renderWithinBoundaryConditions();
floatingGroup.overlay.setBounds();
}

if (typeof activeGroup === 'string') {
Expand Down
1 change: 0 additions & 1 deletion packages/docs/sandboxes/floatinggroup-dockview/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ export const DockviewPersistance = (props: { theme?: string }) => {
<div
style={{
flexGrow: 1,
overflow: 'hidden',
}}
>
<DockviewReact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const HoistedDockviewPanel = <T extends object>(
style={{
position: 'absolute',
overflow: 'hidden',
zIndex: 999,
pointerEvents: 'none', // prevent this wrapper contain stealing events
}}
>
Expand Down

0 comments on commit 430f97f

Please sign in to comment.