mirror of
https://github.com/mathuo/dockview
synced 2025-08-25 03:26:17 +00:00
feat: additional group api
This commit is contained in:
parent
083ca6a8fb
commit
fe3d0b23bd
@ -26,7 +26,9 @@ function isBooleanValue(
|
||||
return typeof canDisplayOverlay === 'boolean';
|
||||
}
|
||||
|
||||
export type CanDisplayOverlay = boolean | ((dragEvent: DragEvent) => boolean);
|
||||
export type CanDisplayOverlay =
|
||||
| boolean
|
||||
| ((dragEvent: DragEvent, state: Quadrant | null) => boolean);
|
||||
|
||||
export class Droptarget extends CompositeDisposable {
|
||||
private target: HTMLElement | undefined;
|
||||
@ -62,11 +64,29 @@ export class Droptarget extends CompositeDisposable {
|
||||
new DragAndDropObserver(this.element, {
|
||||
onDragEnter: () => undefined,
|
||||
onDragOver: (e) => {
|
||||
const width = this.element.clientWidth;
|
||||
const height = this.element.clientHeight;
|
||||
|
||||
if (width === 0 || height === 0) {
|
||||
return; // avoid div!0
|
||||
}
|
||||
|
||||
const x = e.offsetX;
|
||||
const y = e.offsetY;
|
||||
const xp = (100 * x) / width;
|
||||
const yp = (100 * y) / height;
|
||||
|
||||
const quadrant = this.calculateQuadrant(
|
||||
this.options.validOverlays,
|
||||
xp,
|
||||
yp
|
||||
);
|
||||
|
||||
if (isBooleanValue(this.options.canDisplayOverlay)) {
|
||||
if (!this.options.canDisplayOverlay) {
|
||||
return;
|
||||
}
|
||||
} else if (!this.options.canDisplayOverlay(e)) {
|
||||
} else if (!this.options.canDisplayOverlay(e, quadrant)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -90,24 +110,6 @@ export class Droptarget extends CompositeDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const width = this.target.clientWidth;
|
||||
const height = this.target.clientHeight;
|
||||
|
||||
if (width === 0 || height === 0) {
|
||||
return; // avoid div!0
|
||||
}
|
||||
|
||||
const x = e.offsetX;
|
||||
const y = e.offsetY;
|
||||
const xp = (100 * x) / width;
|
||||
const yp = (100 * y) / height;
|
||||
|
||||
const quadrant = this.calculateQuadrant(
|
||||
this.options.validOverlays,
|
||||
xp,
|
||||
yp
|
||||
);
|
||||
|
||||
const isSmallX = width < 100;
|
||||
const isSmallY = height < 100;
|
||||
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
IViewDeserializer,
|
||||
} from '../gridview/gridview';
|
||||
import { GroupviewPanelState, IGroupPanel } from '../groupview/groupPanel';
|
||||
import { GroupPanelViewState } from '../groupview/groupview';
|
||||
import { DockviewComponent } from './dockviewComponent';
|
||||
|
||||
export interface IPanelDeserializer {
|
||||
@ -18,9 +19,10 @@ export class DefaultDeserializer implements IViewDeserializer {
|
||||
}
|
||||
) {}
|
||||
|
||||
public fromJSON(node: ISerializedLeafNode): IGridView {
|
||||
const children = node.data.views;
|
||||
const active = node.data.activeView;
|
||||
public fromJSON(node: ISerializedLeafNode<GroupPanelViewState>): IGridView {
|
||||
const data = node.data;
|
||||
const children = data.views;
|
||||
const active = data.activeView;
|
||||
|
||||
const panels: IGroupPanel[] = [];
|
||||
|
||||
@ -33,7 +35,18 @@ export class DefaultDeserializer implements IViewDeserializer {
|
||||
return this.layout.createGroup({
|
||||
panels,
|
||||
activePanel: panels.find((p) => p.id === active),
|
||||
id: node.data.id,
|
||||
id: data.id,
|
||||
locked: !!data.locked,
|
||||
headerHidden: !!data.headerHidden,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* isGroup
|
||||
*
|
||||
*
|
||||
* panel.group.locked = true
|
||||
* panel.group.header.hiddden = true
|
||||
*
|
||||
*/
|
||||
|
@ -188,7 +188,7 @@ export class DockviewComponent
|
||||
set tabHeight(height: number | undefined) {
|
||||
this.options.tabHeight = height;
|
||||
this._groups.forEach((value) => {
|
||||
value.value.model.tabHeight = height;
|
||||
value.value.model.header.height = height;
|
||||
});
|
||||
}
|
||||
|
||||
@ -704,7 +704,7 @@ export class DockviewComponent
|
||||
view.initialize();
|
||||
|
||||
if (typeof this.options.tabHeight === 'number') {
|
||||
view.model.tabHeight = this.options.tabHeight;
|
||||
view.model.header.height = this.options.tabHeight;
|
||||
}
|
||||
|
||||
return view;
|
||||
|
@ -169,7 +169,7 @@ export class DockviewGroupPanel
|
||||
// the obtain the correct dimensions of the content panel we must deduct the tab height
|
||||
this.api._onDidPanelDimensionChange.fire({
|
||||
width,
|
||||
height: height - (this.group?.model.tabHeight || 0),
|
||||
height: height - (this.group?.model.header.height || 0),
|
||||
});
|
||||
|
||||
this.view?.layout(width, height);
|
||||
|
@ -241,9 +241,9 @@ const serializeBranchNode = <T extends IGridView>(
|
||||
};
|
||||
};
|
||||
|
||||
export interface ISerializedLeafNode {
|
||||
export interface ISerializedLeafNode<T = any> {
|
||||
type: 'leaf';
|
||||
data: any;
|
||||
data: T;
|
||||
size: number;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
@ -48,36 +48,47 @@ interface GroupMoveEvent {
|
||||
index?: number;
|
||||
}
|
||||
|
||||
export interface GroupOptions {
|
||||
interface CoreGroupOptions {
|
||||
locked?: boolean;
|
||||
headerHidden?: boolean;
|
||||
}
|
||||
|
||||
export interface GroupOptions extends CoreGroupOptions {
|
||||
readonly panels?: IGroupPanel[];
|
||||
readonly activePanel?: IGroupPanel;
|
||||
readonly id?: string;
|
||||
tabHeight?: number;
|
||||
}
|
||||
|
||||
export interface GroupviewChangeEvent {
|
||||
readonly kind: GroupChangeKind2;
|
||||
readonly panel?: IGroupPanel;
|
||||
}
|
||||
|
||||
export interface GroupPanelViewState {
|
||||
export interface GroupPanelViewState extends CoreGroupOptions {
|
||||
views: string[];
|
||||
activeView?: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface GroupviewChangeEvent {
|
||||
readonly kind: GroupChangeKind2;
|
||||
readonly panel?: IGroupPanel;
|
||||
}
|
||||
|
||||
export interface GroupviewDropEvent {
|
||||
nativeEvent: DragEvent;
|
||||
position: Position;
|
||||
index?: number;
|
||||
}
|
||||
|
||||
export interface IHeader {
|
||||
hidden: boolean;
|
||||
height: number | undefined;
|
||||
}
|
||||
|
||||
export interface IGroupview extends IDisposable, IGridPanelView {
|
||||
readonly isActive: boolean;
|
||||
readonly size: number;
|
||||
readonly panels: IGroupPanel[];
|
||||
readonly tabHeight: number | undefined;
|
||||
readonly activePanel: IGroupPanel | undefined;
|
||||
locked: boolean;
|
||||
readonly header: IHeader;
|
||||
readonly onDidDrop: Event<GroupviewDropEvent>;
|
||||
// state
|
||||
isPanelActive: (panel: IGroupPanel) => boolean;
|
||||
@ -111,6 +122,7 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
private _activePanel?: IGroupPanel;
|
||||
private watermark?: IWatermarkRenderer;
|
||||
private _isGroupActive = false;
|
||||
private _locked = false;
|
||||
|
||||
private mostRecentlyUsed: IGroupPanel[] = [];
|
||||
|
||||
@ -141,13 +153,12 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
return this._activePanel;
|
||||
}
|
||||
|
||||
get tabHeight(): number | undefined {
|
||||
return this.tabsContainer.height;
|
||||
get locked(): boolean {
|
||||
return this._locked;
|
||||
}
|
||||
|
||||
set tabHeight(height: number | undefined) {
|
||||
this.tabsContainer.height = height;
|
||||
this.layout(this._width, this._height);
|
||||
set locked(value: boolean) {
|
||||
this._locked = value;
|
||||
}
|
||||
|
||||
get isActive(): boolean {
|
||||
@ -188,6 +199,10 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
);
|
||||
}
|
||||
|
||||
get header(): IHeader {
|
||||
return this.tabsContainer;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly container: HTMLElement,
|
||||
private accessor: IDockviewComponent,
|
||||
@ -210,9 +225,14 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
tabHeight: options.tabHeight,
|
||||
});
|
||||
this.contentContainer = new ContentContainer();
|
||||
|
||||
this.dropTarget = new Droptarget(this.contentContainer.element, {
|
||||
validOverlays: 'all',
|
||||
canDisplayOverlay: (event) => {
|
||||
canDisplayOverlay: (event, quadrant) => {
|
||||
if (this.locked && !quadrant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const data = getPanelData();
|
||||
|
||||
if (data) {
|
||||
@ -231,6 +251,9 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
this.contentContainer.element
|
||||
);
|
||||
|
||||
this.header.hidden = !!options.headerHidden;
|
||||
this.locked = !!options.locked;
|
||||
|
||||
this.addDisposables(
|
||||
this._onMove,
|
||||
this._onDidGroupChange,
|
||||
@ -281,11 +304,21 @@ export class Groupview extends CompositeDisposable implements IGroupview {
|
||||
}
|
||||
|
||||
public toJSON(): GroupPanelViewState {
|
||||
return {
|
||||
const result: GroupPanelViewState = {
|
||||
views: this.tabsContainer.panels,
|
||||
activeView: this._activePanel?.id,
|
||||
id: this.id,
|
||||
};
|
||||
|
||||
if (this.locked) {
|
||||
result.locked = true;
|
||||
}
|
||||
|
||||
if (this.header.hidden) {
|
||||
result.headerHidden = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public moveToNext(options?: {
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { IFrameworkPart } from '../panel/types';
|
||||
import { IDockviewComponent } from '../dockview/dockviewComponent';
|
||||
import { GridviewPanelApiImpl } from '../api/gridviewPanelApi';
|
||||
import { Groupview, GroupOptions } from './groupview';
|
||||
import { Groupview, GroupOptions, IGroupview } from './groupview';
|
||||
import { GridviewPanel, IGridviewPanel } from '../gridview/gridviewPanel';
|
||||
|
||||
export interface IGroupviewPanel extends IGridviewPanel {
|
||||
model: Groupview;
|
||||
model: IGroupview;
|
||||
}
|
||||
|
||||
export class GroupviewPanel extends GridviewPanel implements IGroupviewPanel {
|
||||
private readonly _model: Groupview;
|
||||
|
||||
get model(): Groupview {
|
||||
get model(): IGroupview {
|
||||
return this._model;
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ export class GroupviewPanel extends GridviewPanel implements IGroupviewPanel {
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.model.initialize();
|
||||
this._model.initialize();
|
||||
}
|
||||
|
||||
setActive(isActive: boolean): void {
|
||||
|
@ -33,6 +33,7 @@ export interface ITabsContainer extends IDisposable {
|
||||
closePanel: (panel: IGroupPanel) => void;
|
||||
openPanel: (panel: IGroupPanel, index?: number) => void;
|
||||
setActionElement(element: HTMLElement | undefined): void;
|
||||
hidden: boolean;
|
||||
show(): void;
|
||||
hide(): void;
|
||||
}
|
||||
@ -55,6 +56,7 @@ export class TabsContainer
|
||||
private actions: HTMLElement | undefined;
|
||||
|
||||
private _height: number | undefined;
|
||||
private _hidden = false;
|
||||
|
||||
private readonly _onDrop = new Emitter<TabDropIndexEvent>();
|
||||
readonly onDrop: Event<TabDropIndexEvent> = this._onDrop.event;
|
||||
@ -85,12 +87,23 @@ export class TabsContainer
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.element.style.display = '';
|
||||
get hidden(): boolean {
|
||||
return this._hidden;
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.element.style.display = 'none';
|
||||
set hidden(value: boolean) {
|
||||
this._hidden = value;
|
||||
this.element.style.display = value ? 'none' : '';
|
||||
}
|
||||
|
||||
show(): void {
|
||||
if (!this.hidden) {
|
||||
this.element.style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
this._element.style.display = 'none';
|
||||
}
|
||||
|
||||
setActionElement(element: HTMLElement | undefined): void {
|
||||
|
Loading…
x
Reference in New Issue
Block a user