mirror of
https://github.com/mathuo/dockview
synced 2025-02-02 06:25:44 +00:00
feat: setVisible enhancements
This commit is contained in:
parent
3652505a08
commit
ae88703a8b
@ -10,7 +10,7 @@ import { CompositeDisposable } from '../../lifecycle';
|
|||||||
import { Emitter } from '../../events';
|
import { Emitter } from '../../events';
|
||||||
import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from '../../dockview/dockviewPanel';
|
||||||
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
|
||||||
import { fireEvent } from '@testing-library/dom';
|
import { fireEvent, getByTestId, queryByTestId } from '@testing-library/dom';
|
||||||
import { getPanelData } from '../../dnd/dataTransfer';
|
import { getPanelData } from '../../dnd/dataTransfer';
|
||||||
import {
|
import {
|
||||||
GroupDragEvent,
|
GroupDragEvent,
|
||||||
@ -5097,6 +5097,60 @@ describe('dockviewComponent', () => {
|
|||||||
expect(panel4.api.isVisible).toBeTruthy();
|
expect(panel4.api.isVisible).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('setVisible #1', () => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
parentElement: container,
|
||||||
|
createComponent(options) {
|
||||||
|
switch (options.name) {
|
||||||
|
case 'default':
|
||||||
|
return new PanelContentPartTest(
|
||||||
|
options.id,
|
||||||
|
options.name
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new Error(`unsupported`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const api = new DockviewApi(dockview);
|
||||||
|
|
||||||
|
dockview.layout(1000, 1000);
|
||||||
|
|
||||||
|
const panel1 = api.addPanel({
|
||||||
|
id: 'panel1',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
const panel2 = api.addPanel({
|
||||||
|
id: 'panel2',
|
||||||
|
component: 'default',
|
||||||
|
position: { referencePanel: panel1, direction: 'below' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const panel3 = api.addPanel({
|
||||||
|
id: 'panel3',
|
||||||
|
component: 'default',
|
||||||
|
position: { referencePanel: panel1, direction: 'below' },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(api.groups.length).toBe(3);
|
||||||
|
|
||||||
|
panel1.group.api.setVisible(false);
|
||||||
|
panel2.group.api.setVisible(false);
|
||||||
|
panel3.group.api.setVisible(false);
|
||||||
|
|
||||||
|
expect(panel1.group.api.isVisible).toBeFalsy();
|
||||||
|
expect(panel2.group.api.isVisible).toBeFalsy();
|
||||||
|
expect(panel3.group.api.isVisible).toBeFalsy();
|
||||||
|
|
||||||
|
panel1.group.api.setVisible(true);
|
||||||
|
|
||||||
|
expect(panel1.group.api.isVisible).toBeTruthy();
|
||||||
|
expect(panel2.group.api.isVisible).toBeFalsy();
|
||||||
|
expect(panel3.group.api.isVisible).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
describe('addPanel', () => {
|
describe('addPanel', () => {
|
||||||
test('that can add panel', () => {
|
test('that can add panel', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
@ -5429,4 +5483,57 @@ describe('dockviewComponent', () => {
|
|||||||
expect(api.panels.length).toBe(3);
|
expect(api.panels.length).toBe(3);
|
||||||
expect(api.groups.length).toBe(3);
|
expect(api.groups.length).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('that watermark appears when all views are not visible', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
parentElement: container,
|
||||||
|
createComponent(options) {
|
||||||
|
switch (options.name) {
|
||||||
|
case 'default':
|
||||||
|
return new PanelContentPartTest(
|
||||||
|
options.id,
|
||||||
|
options.name
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new Error(`unsupported`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const api = new DockviewApi(dockview);
|
||||||
|
|
||||||
|
dockview.layout(1000, 1000);
|
||||||
|
|
||||||
|
const panel1 = api.addPanel({
|
||||||
|
id: 'panel_1',
|
||||||
|
component: 'default',
|
||||||
|
});
|
||||||
|
const panel2 = api.addPanel({
|
||||||
|
id: 'panel_2',
|
||||||
|
component: 'default',
|
||||||
|
position: {
|
||||||
|
direction: 'right',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let query = queryByTestId(container, 'watermark-component');
|
||||||
|
expect(query).toBeFalsy();
|
||||||
|
|
||||||
|
panel1.group.api.setVisible(false);
|
||||||
|
jest.runAllTicks(); // visibility events check fires on microtask-queue
|
||||||
|
query = queryByTestId(container, 'watermark-component');
|
||||||
|
expect(query).toBeFalsy();
|
||||||
|
|
||||||
|
panel2.group.api.setVisible(false);
|
||||||
|
jest.runAllTicks(); // visibility events check fires on microtask-queue
|
||||||
|
query = queryByTestId(container, 'watermark-component');
|
||||||
|
expect(query).toBeTruthy();
|
||||||
|
|
||||||
|
panel1.group.api.setVisible(true);
|
||||||
|
jest.runAllTicks(); // visibility events check fires on microtask-queue
|
||||||
|
query = queryByTestId(container, 'watermark-component');
|
||||||
|
expect(query).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -17,13 +17,9 @@ class TestPanel implements IGridPanelView {
|
|||||||
_onDidChange = new Emitter<IViewSize | undefined>();
|
_onDidChange = new Emitter<IViewSize | undefined>();
|
||||||
readonly onDidChange = this._onDidChange.event;
|
readonly onDidChange = this._onDidChange.event;
|
||||||
|
|
||||||
get isActive(): boolean {
|
isVisible: boolean = true;
|
||||||
return true;
|
isActive: boolean = true;
|
||||||
}
|
params: Parameters = {};
|
||||||
|
|
||||||
get params(): Parameters {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly id: string,
|
public readonly id: string,
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
IGridView,
|
IGridView,
|
||||||
IViewSize,
|
IViewSize,
|
||||||
SerializedGridview,
|
SerializedGridview,
|
||||||
|
getGridLocation,
|
||||||
orthogonal,
|
orthogonal,
|
||||||
} from '../../gridview/gridview';
|
} from '../../gridview/gridview';
|
||||||
import { Orientation, Sizing } from '../../splitview/splitview';
|
import { Orientation, Sizing } from '../../splitview/splitview';
|
||||||
@ -18,7 +19,7 @@ class MockGridview implements IGridView {
|
|||||||
IViewSize | undefined
|
IViewSize | undefined
|
||||||
>().event;
|
>().event;
|
||||||
element: HTMLElement = document.createElement('div');
|
element: HTMLElement = document.createElement('div');
|
||||||
|
isVisible: boolean = true;
|
||||||
width: number = 0;
|
width: number = 0;
|
||||||
height: number = 0;
|
height: number = 0;
|
||||||
|
|
||||||
@ -1105,4 +1106,102 @@ describe('gridview', () => {
|
|||||||
|
|
||||||
expect(gridview.hasMaximizedView()).toBeFalsy();
|
expect(gridview.hasMaximizedView()).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('visibility check', () => {
|
||||||
|
const gridview = new Gridview(
|
||||||
|
true,
|
||||||
|
{ separatorBorder: '' },
|
||||||
|
Orientation.HORIZONTAL
|
||||||
|
);
|
||||||
|
gridview.layout(1000, 1000);
|
||||||
|
|
||||||
|
const view1 = new MockGridview('1');
|
||||||
|
const view2 = new MockGridview('2');
|
||||||
|
const view3 = new MockGridview('3');
|
||||||
|
const view4 = new MockGridview('4');
|
||||||
|
const view5 = new MockGridview('5');
|
||||||
|
const view6 = new MockGridview('6');
|
||||||
|
|
||||||
|
gridview.addView(view1, Sizing.Distribute, [0]);
|
||||||
|
gridview.addView(view2, Sizing.Distribute, [1]);
|
||||||
|
gridview.addView(view3, Sizing.Distribute, [1, 1]);
|
||||||
|
gridview.addView(view4, Sizing.Distribute, [1, 1, 0]);
|
||||||
|
gridview.addView(view5, Sizing.Distribute, [1, 1, 0, 0]);
|
||||||
|
gridview.addView(view6, Sizing.Distribute, [1, 1, 0, 0, 0]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _____________________________________________
|
||||||
|
* | | |
|
||||||
|
* | | 2 |
|
||||||
|
* | | |
|
||||||
|
* | 1 |_______________________|
|
||||||
|
* | | | 4 |
|
||||||
|
* | | 3 |_____________|
|
||||||
|
* | | | 5 | 6 |
|
||||||
|
* |_____________________|_________|______|______|
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assertVisibility(visibility: boolean[]) {
|
||||||
|
expect(gridview.isViewVisible(getGridLocation(view1.element))).toBe(
|
||||||
|
visibility[0]
|
||||||
|
);
|
||||||
|
expect(gridview.isViewVisible(getGridLocation(view2.element))).toBe(
|
||||||
|
visibility[1]
|
||||||
|
);
|
||||||
|
expect(gridview.isViewVisible(getGridLocation(view3.element))).toBe(
|
||||||
|
visibility[2]
|
||||||
|
);
|
||||||
|
expect(gridview.isViewVisible(getGridLocation(view4.element))).toBe(
|
||||||
|
visibility[3]
|
||||||
|
);
|
||||||
|
expect(gridview.isViewVisible(getGridLocation(view5.element))).toBe(
|
||||||
|
visibility[4]
|
||||||
|
);
|
||||||
|
expect(gridview.isViewVisible(getGridLocation(view6.element))).toBe(
|
||||||
|
visibility[5]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide each view one by one
|
||||||
|
|
||||||
|
assertVisibility([true, true, true, true, true, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view5.element), false);
|
||||||
|
assertVisibility([true, true, true, true, false, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view4.element), false);
|
||||||
|
assertVisibility([true, true, true, false, false, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view1.element), false);
|
||||||
|
assertVisibility([false, true, true, false, false, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view2.element), false);
|
||||||
|
assertVisibility([false, false, true, false, false, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view3.element), false);
|
||||||
|
assertVisibility([false, false, false, false, false, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view6.element), false);
|
||||||
|
assertVisibility([false, false, false, false, false, false]);
|
||||||
|
|
||||||
|
// un-hide each view one by one
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view1.element), true);
|
||||||
|
assertVisibility([true, false, false, false, false, false]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view5.element), true);
|
||||||
|
assertVisibility([true, false, false, false, true, false]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view6.element), true);
|
||||||
|
assertVisibility([true, false, false, false, true, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view2.element), true);
|
||||||
|
assertVisibility([true, true, false, false, true, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view3.element), true);
|
||||||
|
assertVisibility([true, true, true, false, true, true]);
|
||||||
|
|
||||||
|
gridview.setViewVisible(getGridLocation(view4.element), true);
|
||||||
|
assertVisibility([true, true, true, true, true, true]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,10 +8,8 @@ describe('math', () => {
|
|||||||
expect(clamp(55, 40, 50)).toBe(50);
|
expect(clamp(55, 40, 50)).toBe(50);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if min > max', () => {
|
it('if min > max return min', () => {
|
||||||
expect(() => clamp(55, 50, 40)).toThrow(
|
expect(clamp(55, 50, 40)).toBe(50);
|
||||||
'50 > 40 is an invalid condition'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ import { DockviewPanelModel } from './dockviewPanelModel';
|
|||||||
import { getPanelData } from '../dnd/dataTransfer';
|
import { getPanelData } from '../dnd/dataTransfer';
|
||||||
import { Parameters } from '../panel/types';
|
import { Parameters } from '../panel/types';
|
||||||
import { Overlay } from '../dnd/overlay';
|
import { Overlay } from '../dnd/overlay';
|
||||||
import { toggleClass, watchElementResize } from '../dom';
|
import { addTestId, toggleClass, watchElementResize } from '../dom';
|
||||||
import { DockviewFloatingGroupPanel } from './dockviewFloatingGroupPanel';
|
import { DockviewFloatingGroupPanel } from './dockviewFloatingGroupPanel';
|
||||||
import {
|
import {
|
||||||
GroupDragEvent,
|
GroupDragEvent,
|
||||||
@ -372,6 +372,9 @@ export class DockviewComponent
|
|||||||
this._onDidRemoveGroup,
|
this._onDidRemoveGroup,
|
||||||
this._onDidActiveGroupChange,
|
this._onDidActiveGroupChange,
|
||||||
this._onUnhandledDragOverEvent,
|
this._onUnhandledDragOverEvent,
|
||||||
|
this.onDidViewVisibilityChangeMicroTaskQueue(() => {
|
||||||
|
this.updateWatermark();
|
||||||
|
}),
|
||||||
this.onDidAdd((event) => {
|
this.onDidAdd((event) => {
|
||||||
if (!this._moving) {
|
if (!this._moving) {
|
||||||
this._onDidAddGroup.fire(event);
|
this._onDidAddGroup.fire(event);
|
||||||
@ -1519,6 +1522,7 @@ export class DockviewComponent
|
|||||||
|
|
||||||
const watermarkContainer = document.createElement('div');
|
const watermarkContainer = document.createElement('div');
|
||||||
watermarkContainer.className = 'dv-watermark-container';
|
watermarkContainer.className = 'dv-watermark-container';
|
||||||
|
addTestId(watermarkContainer, 'watermark-component');
|
||||||
watermarkContainer.appendChild(this.watermark.element);
|
watermarkContainer.appendChild(this.watermark.element);
|
||||||
|
|
||||||
this.gridview.element.appendChild(watermarkContainer);
|
this.gridview.element.appendChild(watermarkContainer);
|
||||||
|
@ -253,3 +253,7 @@ export function isInDocument(element: Element): boolean {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addTestId(element: HTMLElement, id: string): void {
|
||||||
|
element.setAttribute('data-testid', id);
|
||||||
|
}
|
||||||
|
@ -93,6 +93,10 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
readonly onDidLayoutChange: Event<void> =
|
readonly onDidLayoutChange: Event<void> =
|
||||||
this._bufferOnDidLayoutChange.onEvent;
|
this._bufferOnDidLayoutChange.onEvent;
|
||||||
|
|
||||||
|
private readonly _onDidViewVisibilityChangeMicroTaskQueue = new AsapEvent();
|
||||||
|
readonly onDidViewVisibilityChangeMicroTaskQueue =
|
||||||
|
this._onDidViewVisibilityChangeMicroTaskQueue.onEvent;
|
||||||
|
|
||||||
get id(): string {
|
get id(): string {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
@ -158,6 +162,12 @@ export abstract class BaseGrid<T extends IGridPanelView>
|
|||||||
this.layout(0, 0, true); // set some elements height/widths
|
this.layout(0, 0, true); // set some elements height/widths
|
||||||
|
|
||||||
this.addDisposables(
|
this.addDisposables(
|
||||||
|
this.gridview.onDidViewVisibilityChange(() =>
|
||||||
|
this._onDidViewVisibilityChangeMicroTaskQueue.fire()
|
||||||
|
),
|
||||||
|
this.onDidViewVisibilityChangeMicroTaskQueue(() => {
|
||||||
|
this.layout(this.width, this.height, true);
|
||||||
|
}),
|
||||||
Disposable.from(() => {
|
Disposable.from(() => {
|
||||||
this.element.parentElement?.removeChild(this.element);
|
this.element.parentElement?.removeChild(this.element);
|
||||||
}),
|
}),
|
||||||
|
@ -33,9 +33,12 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
|
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
|
||||||
this._onDidChange.event;
|
this._onDidChange.event;
|
||||||
|
|
||||||
private readonly _onDidVisibilityChange = new Emitter<boolean>();
|
private readonly _onDidVisibilityChange = new Emitter<{
|
||||||
readonly onDidVisibilityChange: Event<boolean> =
|
visible: boolean;
|
||||||
this._onDidVisibilityChange.event;
|
}>();
|
||||||
|
readonly onDidVisibilityChange: Event<{
|
||||||
|
visible: boolean;
|
||||||
|
}> = this._onDidVisibilityChange.event;
|
||||||
|
|
||||||
get width(): number {
|
get width(): number {
|
||||||
return this.orientation === Orientation.HORIZONTAL
|
return this.orientation === Orientation.HORIZONTAL
|
||||||
@ -200,10 +203,8 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
this.setupChildrenEvents();
|
this.setupChildrenEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(visible: boolean): void {
|
setVisible(_visible: boolean): void {
|
||||||
for (const child of this.children) {
|
// noop
|
||||||
child.setVisible(visible);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isChildVisible(index: number): boolean {
|
isChildVisible(index: number): boolean {
|
||||||
@ -224,7 +225,9 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wereAllChildrenHidden = this.splitview.contentSize === 0;
|
const wereAllChildrenHidden = this.splitview.contentSize === 0;
|
||||||
|
|
||||||
this.splitview.setViewVisible(index, visible);
|
this.splitview.setViewVisible(index, visible);
|
||||||
|
// }
|
||||||
const areAllChildrenHidden = this.splitview.contentSize === 0;
|
const areAllChildrenHidden = this.splitview.contentSize === 0;
|
||||||
|
|
||||||
// If all children are hidden then the parent should hide the entire splitview
|
// If all children are hidden then the parent should hide the entire splitview
|
||||||
@ -233,7 +236,7 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
(visible && wereAllChildrenHidden) ||
|
(visible && wereAllChildrenHidden) ||
|
||||||
(!visible && areAllChildrenHidden)
|
(!visible && areAllChildrenHidden)
|
||||||
) {
|
) {
|
||||||
this._onDidVisibilityChange.fire(visible);
|
this._onDidVisibilityChange.fire({ visible });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +338,7 @@ export class BranchNode extends CompositeDisposable implements IView {
|
|||||||
}),
|
}),
|
||||||
...this.children.map((c, i) => {
|
...this.children.map((c, i) => {
|
||||||
if (c instanceof BranchNode) {
|
if (c instanceof BranchNode) {
|
||||||
return c.onDidVisibilityChange((visible) => {
|
return c.onDidVisibilityChange(({ visible }) => {
|
||||||
this.setChildVisible(i, visible);
|
this.setChildVisible(i, visible);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -171,6 +171,7 @@ export interface IGridView {
|
|||||||
readonly maximumWidth: number;
|
readonly maximumWidth: number;
|
||||||
readonly minimumHeight: number;
|
readonly minimumHeight: number;
|
||||||
readonly maximumHeight: number;
|
readonly maximumHeight: number;
|
||||||
|
readonly isVisible: boolean;
|
||||||
priority?: LayoutPriority;
|
priority?: LayoutPriority;
|
||||||
layout(width: number, height: number): void;
|
layout(width: number, height: number): void;
|
||||||
toJSON(): object;
|
toJSON(): object;
|
||||||
@ -287,6 +288,9 @@ export class Gridview implements IDisposable {
|
|||||||
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
|
readonly onDidChange: Event<{ size?: number; orthogonalSize?: number }> =
|
||||||
this._onDidChange.event;
|
this._onDidChange.event;
|
||||||
|
|
||||||
|
private readonly _onDidViewVisibilityChange = new Emitter<void>();
|
||||||
|
readonly onDidViewVisibilityChange = this._onDidViewVisibilityChange.event;
|
||||||
|
|
||||||
private readonly _onDidMaximizedNodeChange = new Emitter<void>();
|
private readonly _onDidMaximizedNodeChange = new Emitter<void>();
|
||||||
readonly onDidMaximizedNodeChange = this._onDidMaximizedNodeChange.event;
|
readonly onDidMaximizedNodeChange = this._onDidMaximizedNodeChange.event;
|
||||||
|
|
||||||
@ -453,6 +457,8 @@ export class Gridview implements IDisposable {
|
|||||||
this.disposable.dispose();
|
this.disposable.dispose();
|
||||||
this._onDidChange.dispose();
|
this._onDidChange.dispose();
|
||||||
this._onDidMaximizedNodeChange.dispose();
|
this._onDidMaximizedNodeChange.dispose();
|
||||||
|
this._onDidViewVisibilityChange.dispose();
|
||||||
|
|
||||||
this.root.dispose();
|
this.root.dispose();
|
||||||
this._maximizedNode = undefined;
|
this._maximizedNode = undefined;
|
||||||
this.element.remove();
|
this.element.remove();
|
||||||
@ -531,12 +537,12 @@ export class Gridview implements IDisposable {
|
|||||||
children
|
children
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
result = new LeafNode(
|
const view = deserializer.fromJSON(node);
|
||||||
deserializer.fromJSON(node),
|
if (typeof node.visible === 'boolean') {
|
||||||
orientation,
|
view.setVisible?.(node.visible);
|
||||||
orthogonalSize,
|
}
|
||||||
node.size
|
|
||||||
);
|
result = new LeafNode(view, orientation, orthogonalSize, node.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -723,6 +729,8 @@ export class Gridview implements IDisposable {
|
|||||||
throw new Error('Invalid from location');
|
throw new Error('Invalid from location');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._onDidViewVisibilityChange.fire();
|
||||||
|
|
||||||
parent.setChildVisible(index, visible);
|
parent.setChildVisible(index, visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +126,10 @@ export abstract class GridviewPanel<
|
|||||||
return this.api.isActive;
|
return this.api.isActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isVisible(): boolean {
|
||||||
|
return this.api.isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
component: string,
|
component: string,
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
export const clamp = (value: number, min: number, max: number): number => {
|
export const clamp = (value: number, min: number, max: number): number => {
|
||||||
if (min > max) {
|
if (min > max) {
|
||||||
throw new Error(`${min} > ${max} is an invalid condition`);
|
/**
|
||||||
|
* caveat: an error should be thrown here if this was a proper `clamp` function but we need to handle
|
||||||
|
* cases where `min` > `max` and in those cases return `min`.
|
||||||
|
*/
|
||||||
|
return min;
|
||||||
}
|
}
|
||||||
return Math.min(max, Math.max(value, min));
|
return Math.min(max, Math.max(value, min));
|
||||||
};
|
};
|
||||||
|
@ -291,12 +291,8 @@ export class Splitview {
|
|||||||
throw new Error('Index out of bounds');
|
throw new Error('Index out of bounds');
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleClass(this.container, 'visible', visible);
|
|
||||||
|
|
||||||
const viewItem = this.viewItems[index];
|
const viewItem = this.viewItems[index];
|
||||||
|
|
||||||
toggleClass(this.container, 'visible', visible);
|
|
||||||
|
|
||||||
viewItem.setVisible(visible, viewItem.size);
|
viewItem.setVisible(visible, viewItem.size);
|
||||||
|
|
||||||
this.distributeEmptySpace(index);
|
this.distributeEmptySpace(index);
|
||||||
|
@ -77,6 +77,11 @@
|
|||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
color: gray;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ export const GridActions = (props: {
|
|||||||
|
|
||||||
const onSave = () => {
|
const onSave = () => {
|
||||||
if (props.api) {
|
if (props.api) {
|
||||||
|
console.log(props.api.toJSON());
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'dv-demo-state',
|
'dv-demo-state',
|
||||||
JSON.stringify(props.api.toJSON())
|
JSON.stringify(props.api.toJSON())
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { DockviewApi, DockviewGroupLocation } from 'dockview';
|
import {
|
||||||
|
DockviewApi,
|
||||||
|
DockviewGroupLocation,
|
||||||
|
DockviewGroupPanel,
|
||||||
|
} from 'dockview';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
const GroupAction = (props: {
|
const GroupAction = (props: {
|
||||||
@ -12,14 +16,27 @@ const GroupAction = (props: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const isActive = props.activeGroup === props.groupId;
|
const isActive = props.activeGroup === props.groupId;
|
||||||
const group = React.useMemo(
|
|
||||||
() => props.api.getGroup(props.groupId),
|
const [group, setGroup] = React.useState<DockviewGroupPanel | undefined>(
|
||||||
[props.api, props.groupId]
|
undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const disposable = props.api.onDidLayoutFromJSON(() => {
|
||||||
|
setGroup(props.api.getGroup(props.groupId));
|
||||||
|
});
|
||||||
|
|
||||||
|
setGroup(props.api.getGroup(props.groupId));
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
}, [props.api, props.groupId]);
|
||||||
|
|
||||||
const [location, setLocation] =
|
const [location, setLocation] =
|
||||||
React.useState<DockviewGroupLocation | null>(null);
|
React.useState<DockviewGroupLocation | null>(null);
|
||||||
const [isMaximized, setIsMaximized] = React.useState<boolean>(false);
|
const [isMaximized, setIsMaximized] = React.useState<boolean>(false);
|
||||||
|
const [isVisible, setIsVisible] = React.useState<boolean>(true);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!group) {
|
if (!group) {
|
||||||
@ -35,12 +52,18 @@ const GroupAction = (props: {
|
|||||||
setIsMaximized(group.api.isMaximized());
|
setIsMaximized(group.api.isMaximized());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const disposable3 = group.api.onDidVisibilityChange(() => {
|
||||||
|
setIsVisible(group.api.isVisible);
|
||||||
|
});
|
||||||
|
|
||||||
setLocation(group.api.location);
|
setLocation(group.api.location);
|
||||||
setIsMaximized(group.api.isMaximized());
|
setIsMaximized(group.api.isMaximized());
|
||||||
|
setIsVisible(group.api.isVisible);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
disposable2.dispose();
|
disposable2.dispose();
|
||||||
|
disposable3.dispose();
|
||||||
};
|
};
|
||||||
}, [group]);
|
}, [group]);
|
||||||
|
|
||||||
@ -107,6 +130,23 @@ const GroupAction = (props: {
|
|||||||
fullscreen
|
fullscreen
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
className="demo-icon-button"
|
||||||
|
onClick={() => {
|
||||||
|
console.log(group);
|
||||||
|
if (group) {
|
||||||
|
if (group.api.isVisible) {
|
||||||
|
group.api.setVisible(false);
|
||||||
|
} else {
|
||||||
|
group.api.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="material-symbols-outlined">
|
||||||
|
{isVisible ? 'visibility' : 'visibility_off'}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
className="demo-icon-button"
|
className="demo-icon-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { DockviewApi } from 'dockview';
|
import { DockviewApi, IDockviewPanel } from 'dockview';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
const PanelAction = (props: {
|
const PanelAction = (props: {
|
||||||
panels: string[];
|
panels: string[];
|
||||||
@ -9,6 +10,50 @@ const PanelAction = (props: {
|
|||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
props.api.getPanel(props.panelId)?.focus();
|
props.api.getPanel(props.panelId)?.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const panel = props.api.getPanel(props.panelId);
|
||||||
|
if (panel) {
|
||||||
|
const disposable = panel.api.onDidVisibilityChange((event) => {
|
||||||
|
setVisible(event.isVisible);
|
||||||
|
});
|
||||||
|
setVisible(panel.api.isVisible);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, [props.api, props.panelId]);
|
||||||
|
|
||||||
|
const [panel, setPanel] = React.useState<IDockviewPanel | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const list = [
|
||||||
|
props.api.onDidLayoutFromJSON(() => {
|
||||||
|
setPanel(props.api.getPanel(props.panelId));
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (panel) {
|
||||||
|
const disposable = panel.api.onDidVisibilityChange((event) => {
|
||||||
|
setVisible(event.isVisible);
|
||||||
|
});
|
||||||
|
setVisible(panel.api.isVisible);
|
||||||
|
|
||||||
|
list.push(disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPanel(props.api.getPanel(props.panelId));
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
list.forEach((l) => l.dispose());
|
||||||
|
};
|
||||||
|
}, [props.api, props.panelId]);
|
||||||
|
|
||||||
|
const [visible, setVisible] = React.useState<boolean>(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="button-action">
|
<div className="button-action">
|
||||||
<div style={{ display: 'flex' }}>
|
<div style={{ display: 'flex' }}>
|
||||||
@ -57,6 +102,15 @@ const PanelAction = (props: {
|
|||||||
>
|
>
|
||||||
<span className="material-symbols-outlined">close</span>
|
<span className="material-symbols-outlined">close</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
title="Panel visiblity cannot be edited manually."
|
||||||
|
disabled={true}
|
||||||
|
className="demo-icon-button"
|
||||||
|
>
|
||||||
|
<span className="material-symbols-outlined">
|
||||||
|
{visible ? 'visibility' : 'visibility_off'}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
1
packages/docs/static/img/vue-icon.svg
vendored
Normal file
1
packages/docs/static/img/vue-icon.svg
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
After Width: | Height: | Size: 276 B |
Loading…
Reference in New Issue
Block a user