flexlayout-react 0.8.10 → 0.8.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.txt +9 -0
- package/README.md +28 -20
- package/declarations/view/BorderTab.d.ts +1 -2
- package/declarations/view/Icons.d.ts +7 -8
- package/declarations/view/Layout.d.ts +1 -1
- package/declarations/view/SizeTracker.d.ts +1 -1
- package/dist/flexlayout.js +49 -29
- package/dist/flexlayout_min.js +1 -1
- package/dist/flexlayout_min.js.LICENSE.txt +10 -0
- package/dist/src/Attribute.js +43 -0
- package/dist/src/Attribute.js.map +1 -0
- package/dist/src/AttributeDefinitions.js +132 -0
- package/dist/src/AttributeDefinitions.js.map +1 -0
- package/dist/src/DockLocation.js +121 -0
- package/dist/src/DockLocation.js.map +1 -0
- package/dist/src/DropInfo.js +10 -0
- package/dist/src/DropInfo.js.map +1 -0
- package/dist/src/I18nLabel.js +14 -0
- package/dist/src/I18nLabel.js.map +1 -0
- package/dist/src/Orientation.js +23 -0
- package/dist/src/Orientation.js.map +1 -0
- package/dist/src/Rect.js +111 -0
- package/dist/src/Rect.js.map +1 -0
- package/dist/src/Types.js +95 -0
- package/dist/src/Types.js.map +1 -0
- package/dist/src/index.js +22 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/model/Action.js +7 -0
- package/dist/src/model/Action.js.map +1 -0
- package/dist/src/model/Actions.js +170 -0
- package/dist/src/model/Actions.js.map +1 -0
- package/dist/src/model/BorderNode.js +390 -0
- package/dist/src/model/BorderNode.js.map +1 -0
- package/dist/src/model/BorderSet.js +67 -0
- package/dist/src/model/BorderSet.js.map +1 -0
- package/dist/src/model/ICloseType.js +7 -0
- package/dist/src/model/ICloseType.js.map +1 -0
- package/dist/src/model/IDraggable.js +2 -0
- package/dist/src/model/IDraggable.js.map +1 -0
- package/dist/src/model/IDropTarget.js +2 -0
- package/dist/src/model/IDropTarget.js.map +1 -0
- package/dist/src/model/IJsonModel.js +2 -0
- package/dist/src/model/IJsonModel.js.map +1 -0
- package/dist/src/model/LayoutWindow.js +81 -0
- package/dist/src/model/LayoutWindow.js.map +1 -0
- package/dist/src/model/Model.js +608 -0
- package/dist/src/model/Model.js.map +1 -0
- package/dist/src/model/Node.js +218 -0
- package/dist/src/model/Node.js.map +1 -0
- package/dist/src/model/RowNode.js +492 -0
- package/dist/src/model/RowNode.js.map +1 -0
- package/dist/src/model/TabNode.js +293 -0
- package/dist/src/model/TabNode.js.map +1 -0
- package/dist/src/model/TabSetNode.js +469 -0
- package/dist/src/model/TabSetNode.js.map +1 -0
- package/dist/src/model/Utils.js +48 -0
- package/dist/src/model/Utils.js.map +1 -0
- package/dist/src/view/BorderButton.js +126 -0
- package/dist/src/view/BorderButton.js.map +1 -0
- package/dist/src/view/BorderTab.js +44 -0
- package/dist/src/view/BorderTab.js.map +1 -0
- package/dist/src/view/BorderTabSet.js +138 -0
- package/dist/src/view/BorderTabSet.js.map +1 -0
- package/dist/src/view/DragContainer.js +16 -0
- package/dist/src/view/DragContainer.js.map +1 -0
- package/dist/src/view/ErrorBoundary.js +24 -0
- package/dist/src/view/ErrorBoundary.js.map +1 -0
- package/dist/src/view/Icons.js +29 -0
- package/dist/src/view/Icons.js.map +1 -0
- package/dist/src/view/Layout.js +881 -0
- package/dist/src/view/Layout.js.map +1 -0
- package/dist/src/view/Overlay.js +9 -0
- package/dist/src/view/Overlay.js.map +1 -0
- package/dist/src/view/PopoutWindow.js +129 -0
- package/dist/src/view/PopoutWindow.js.map +1 -0
- package/dist/src/view/PopupMenu.js +89 -0
- package/dist/src/view/PopupMenu.js.map +1 -0
- package/dist/src/view/Row.js +46 -0
- package/dist/src/view/Row.js.map +1 -0
- package/dist/src/view/SizeTracker.js +12 -0
- package/dist/src/view/SizeTracker.js.map +1 -0
- package/dist/src/view/Splitter.js +192 -0
- package/dist/src/view/Splitter.js.map +1 -0
- package/dist/src/view/Tab.js +91 -0
- package/dist/src/view/Tab.js.map +1 -0
- package/dist/src/view/TabButton.js +124 -0
- package/dist/src/view/TabButton.js.map +1 -0
- package/dist/src/view/TabButtonStamp.js +15 -0
- package/dist/src/view/TabButtonStamp.js.map +1 -0
- package/dist/src/view/TabOverflowHook.js +266 -0
- package/dist/src/view/TabOverflowHook.js.map +1 -0
- package/dist/src/view/TabSet.js +256 -0
- package/dist/src/view/TabSet.js.map +1 -0
- package/dist/src/view/Utils.js +110 -0
- package/dist/src/view/Utils.js.map +1 -0
- package/lib/view/BorderButton.js +6 -8
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTab.js +18 -9
- package/lib/view/BorderTab.js.map +1 -1
- package/lib/view/BorderTabSet.js +11 -17
- package/lib/view/BorderTabSet.js.map +1 -1
- package/lib/view/DragContainer.js +2 -2
- package/lib/view/DragContainer.js.map +1 -1
- package/lib/view/ErrorBoundary.js +2 -2
- package/lib/view/ErrorBoundary.js.map +1 -1
- package/lib/view/Icons.js +8 -20
- package/lib/view/Icons.js.map +1 -1
- package/lib/view/Layout.js +36 -79
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/Overlay.js +2 -2
- package/lib/view/Overlay.js.map +1 -1
- package/lib/view/PopupMenu.js +4 -5
- package/lib/view/PopupMenu.js.map +1 -1
- package/lib/view/Row.js +5 -4
- package/lib/view/Row.js.map +1 -1
- package/lib/view/SizeTracker.js +2 -1
- package/lib/view/SizeTracker.js.map +1 -1
- package/lib/view/Splitter.js +9 -4
- package/lib/view/Splitter.js.map +1 -1
- package/lib/view/Tab.js +3 -4
- package/lib/view/Tab.js.map +1 -1
- package/lib/view/TabButton.js +6 -8
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabButtonStamp.js +4 -6
- package/lib/view/TabButtonStamp.js.map +1 -1
- package/lib/view/TabSet.js +38 -42
- package/lib/view/TabSet.js.map +1 -1
- package/lib/view/Utils.js +3 -3
- package/lib/view/Utils.js.map +1 -1
- package/package.json +87 -82
- package/src/view/BorderTab.tsx +18 -7
- package/src/view/Icons.tsx +0 -2
- package/src/view/Layout.tsx +2 -2
- package/src/view/Overlay.tsx +0 -1
- package/src/view/Splitter.tsx +6 -0
- package/src/view/TabButtonStamp.tsx +0 -1
- package/src/view/TabSet.tsx +16 -7
- package/eslint.config.mjs +0 -19
|
@@ -0,0 +1,881 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { createRoot } from "react-dom/client";
|
|
5
|
+
import { DockLocation } from "../DockLocation";
|
|
6
|
+
import { I18nLabel } from "../I18nLabel";
|
|
7
|
+
import { Orientation } from "../Orientation";
|
|
8
|
+
import { Rect } from "../Rect";
|
|
9
|
+
import { CLASSES } from "../Types";
|
|
10
|
+
import { Actions } from "../model/Actions";
|
|
11
|
+
import { BorderNode } from "../model/BorderNode";
|
|
12
|
+
import { Model } from "../model/Model";
|
|
13
|
+
import { TabNode } from "../model/TabNode";
|
|
14
|
+
import { TabSetNode } from "../model/TabSetNode";
|
|
15
|
+
import { BorderTab } from "./BorderTab";
|
|
16
|
+
import { BorderTabSet } from "./BorderTabSet";
|
|
17
|
+
import { DragContainer } from "./DragContainer";
|
|
18
|
+
import { ErrorBoundary } from "./ErrorBoundary";
|
|
19
|
+
import { PopoutWindow } from "./PopoutWindow";
|
|
20
|
+
import { AsterickIcon, CloseIcon, EdgeIcon, MaximizeIcon, OverflowIcon, PopoutIcon, RestoreIcon } from "./Icons";
|
|
21
|
+
import { Overlay } from "./Overlay";
|
|
22
|
+
import { Row } from "./Row";
|
|
23
|
+
import { Tab } from "./Tab";
|
|
24
|
+
import { copyInlineStyles, enablePointerOnIFrames, isDesktop, isSafari } from "./Utils";
|
|
25
|
+
import { TabButtonStamp } from "./TabButtonStamp";
|
|
26
|
+
import { SizeTracker } from "./SizeTracker";
|
|
27
|
+
/**
|
|
28
|
+
* A React component that hosts a multi-tabbed layout
|
|
29
|
+
*/
|
|
30
|
+
export class Layout extends React.Component {
|
|
31
|
+
/** @internal */
|
|
32
|
+
constructor(props) {
|
|
33
|
+
super(props);
|
|
34
|
+
this.selfRef = React.createRef();
|
|
35
|
+
this.revision = 0;
|
|
36
|
+
}
|
|
37
|
+
/** re-render the layout */
|
|
38
|
+
redraw() {
|
|
39
|
+
this.selfRef.current.redraw("parent " + this.revision);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Adds a new tab to the given tabset
|
|
43
|
+
* @param tabsetId the id of the tabset where the new tab will be added
|
|
44
|
+
* @param json the json for the new tab node
|
|
45
|
+
* @returns the added tab node or undefined
|
|
46
|
+
*/
|
|
47
|
+
addTabToTabSet(tabsetId, json) {
|
|
48
|
+
return this.selfRef.current.addTabToTabSet(tabsetId, json);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Adds a new tab by dragging an item to the drop location, must be called from within an HTML
|
|
52
|
+
* drag start handler. You can use the setDragComponent() method to set the drag image before calling this
|
|
53
|
+
* method.
|
|
54
|
+
* @param event the drag start event
|
|
55
|
+
* @param json the json for the new tab node
|
|
56
|
+
* @param onDrop a callback to call when the drag is complete
|
|
57
|
+
*/
|
|
58
|
+
addTabWithDragAndDrop(event, json, onDrop) {
|
|
59
|
+
this.selfRef.current.addTabWithDragAndDrop(event, json, onDrop);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Move a tab/tabset using drag and drop, must be called from within an HTML
|
|
63
|
+
* drag start handler
|
|
64
|
+
* @param event the drag start event
|
|
65
|
+
* @param node the tab or tabset to drag
|
|
66
|
+
*/
|
|
67
|
+
moveTabWithDragAndDrop(event, node) {
|
|
68
|
+
this.selfRef.current.moveTabWithDragAndDrop(event, node);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Adds a new tab to the active tabset (if there is one)
|
|
72
|
+
* @param json the json for the new tab node
|
|
73
|
+
* @returns the added tab node or undefined
|
|
74
|
+
*/
|
|
75
|
+
addTabToActiveTabSet(json) {
|
|
76
|
+
return this.selfRef.current.addTabToActiveTabSet(json);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sets the drag image from a react component for a drag event
|
|
80
|
+
* @param event the drag event
|
|
81
|
+
* @param component the react component to be used for the drag image
|
|
82
|
+
* @param x the x position of the drag cursor on the image
|
|
83
|
+
* @param y the x position of the drag cursor on the image
|
|
84
|
+
*/
|
|
85
|
+
setDragComponent(event, component, x, y) {
|
|
86
|
+
this.selfRef.current.setDragComponent(event, component, x, y);
|
|
87
|
+
}
|
|
88
|
+
/** Get the root div element of the layout */
|
|
89
|
+
getRootDiv() {
|
|
90
|
+
return this.selfRef.current.getRootDiv();
|
|
91
|
+
}
|
|
92
|
+
/** @internal */
|
|
93
|
+
render() {
|
|
94
|
+
return (_jsx(LayoutInternal, Object.assign({ ref: this.selfRef }, this.props, { renderRevision: this.revision++ })));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** @internal */
|
|
98
|
+
export class LayoutInternal extends React.Component {
|
|
99
|
+
// private renderCount: any;
|
|
100
|
+
constructor(props) {
|
|
101
|
+
super(props);
|
|
102
|
+
this.moveableElementMap = new Map();
|
|
103
|
+
this.dragEnterCount = 0;
|
|
104
|
+
this.dragging = false;
|
|
105
|
+
this.updateLayoutMetrics = () => {
|
|
106
|
+
if (this.findBorderBarSizeRef.current) {
|
|
107
|
+
const borderBarSize = this.findBorderBarSizeRef.current.getBoundingClientRect().height;
|
|
108
|
+
if (borderBarSize !== this.state.calculatedBorderBarSize) {
|
|
109
|
+
this.setState({ calculatedBorderBarSize: borderBarSize });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
this.onModelChange = (action) => {
|
|
114
|
+
this.redrawInternal("model change");
|
|
115
|
+
if (this.props.onModelChange) {
|
|
116
|
+
this.props.onModelChange(this.props.model, action);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
this.updateRect = () => {
|
|
120
|
+
const rect = this.getDomRect();
|
|
121
|
+
if (!rect.equals(this.state.rect) && rect.width !== 0 && rect.height !== 0) {
|
|
122
|
+
// console.log("updateRect", rect.floor());
|
|
123
|
+
this.setState({ rect });
|
|
124
|
+
if (this.windowId !== Model.MAIN_WINDOW_ID) {
|
|
125
|
+
this.redrawInternal("rect updated");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
this.getClassName = (defaultClassName) => {
|
|
130
|
+
if (this.props.classNameMapper === undefined) {
|
|
131
|
+
return defaultClassName;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
return this.props.classNameMapper(defaultClassName);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
this.onCloseWindow = (windowLayout) => {
|
|
138
|
+
this.doAction(Actions.closeWindow(windowLayout.windowId));
|
|
139
|
+
};
|
|
140
|
+
this.onSetWindow = (windowLayout, window) => {
|
|
141
|
+
};
|
|
142
|
+
this.showControlInPortal = (control, element) => {
|
|
143
|
+
const portal = createPortal(control, element);
|
|
144
|
+
this.setState({ portal });
|
|
145
|
+
};
|
|
146
|
+
this.hideControlInPortal = () => {
|
|
147
|
+
this.setState({ portal: undefined });
|
|
148
|
+
};
|
|
149
|
+
this.getIcons = () => {
|
|
150
|
+
return this.icons;
|
|
151
|
+
};
|
|
152
|
+
this.setDragNode = (event, node) => {
|
|
153
|
+
LayoutInternal.dragState = new DragState(this.mainLayout, DragSource.Internal, node, undefined, undefined);
|
|
154
|
+
// Note: can only set (very) limited types on android! so cannot set json
|
|
155
|
+
// Note: must set text/plain for android to allow drag,
|
|
156
|
+
// so just set a simple message indicating its a flexlayout drag (this is not used anywhere else)
|
|
157
|
+
event.dataTransfer.setData('text/plain', "--flexlayout--");
|
|
158
|
+
event.dataTransfer.effectAllowed = "copyMove";
|
|
159
|
+
event.dataTransfer.dropEffect = "move";
|
|
160
|
+
this.dragEnterCount = 0;
|
|
161
|
+
if (node instanceof TabSetNode) {
|
|
162
|
+
let rendered = false;
|
|
163
|
+
let content = this.i18nName(I18nLabel.Move_Tabset);
|
|
164
|
+
if (node.getChildren().length > 0) {
|
|
165
|
+
content = this.i18nName(I18nLabel.Move_Tabs).replace("?", String(node.getChildren().length));
|
|
166
|
+
}
|
|
167
|
+
if (this.props.onRenderDragRect) {
|
|
168
|
+
const dragComponent = this.props.onRenderDragRect(content, node, undefined);
|
|
169
|
+
if (dragComponent) {
|
|
170
|
+
this.setDragComponent(event, dragComponent, 10, 10);
|
|
171
|
+
rendered = true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (!rendered) {
|
|
175
|
+
this.setDragComponent(event, content, 10, 10);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
const element = event.target;
|
|
180
|
+
const rect = element.getBoundingClientRect();
|
|
181
|
+
const offsetX = event.clientX - rect.left;
|
|
182
|
+
const offsetY = event.clientY - rect.top;
|
|
183
|
+
const parentNode = node === null || node === void 0 ? void 0 : node.getParent();
|
|
184
|
+
const isInVerticalBorder = parentNode instanceof BorderNode && parentNode.getOrientation() === Orientation.HORZ;
|
|
185
|
+
const x = isInVerticalBorder ? 10 : offsetX;
|
|
186
|
+
const y = isInVerticalBorder ? 10 : offsetY;
|
|
187
|
+
let rendered = false;
|
|
188
|
+
if (this.props.onRenderDragRect) {
|
|
189
|
+
const content = _jsx(TabButtonStamp, { layout: this, node: node }, node.getId());
|
|
190
|
+
const dragComponent = this.props.onRenderDragRect(content, node, undefined);
|
|
191
|
+
if (dragComponent) {
|
|
192
|
+
this.setDragComponent(event, dragComponent, x, y);
|
|
193
|
+
rendered = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (!rendered) {
|
|
197
|
+
if (isSafari()) { // safari doesnt render the offscreen tabstamps
|
|
198
|
+
this.setDragComponent(event, _jsx(TabButtonStamp, { node: node, layout: this }), x, y);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
event.dataTransfer.setDragImage(node.getTabStamp(), x, y);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
this.onDragEnterRaw = (event) => {
|
|
207
|
+
this.dragEnterCount++;
|
|
208
|
+
if (this.dragEnterCount === 1) {
|
|
209
|
+
this.onDragEnter(event);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
this.onDragLeaveRaw = (event) => {
|
|
213
|
+
this.dragEnterCount--;
|
|
214
|
+
if (this.dragEnterCount === 0) {
|
|
215
|
+
this.onDragLeave(event);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
this.onDragEnter = (event) => {
|
|
219
|
+
// console.log("onDragEnter", this.windowId, this.dragEnterCount);
|
|
220
|
+
var _a;
|
|
221
|
+
if (!LayoutInternal.dragState && this.props.onExternalDrag) { // not internal dragging
|
|
222
|
+
const externalDrag = this.props.onExternalDrag(event);
|
|
223
|
+
if (externalDrag) {
|
|
224
|
+
const tempNode = TabNode.fromJson(externalDrag.json, this.props.model, false);
|
|
225
|
+
LayoutInternal.dragState = new DragState(this.mainLayout, DragSource.External, tempNode, externalDrag.json, externalDrag.onDrop);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (LayoutInternal.dragState) {
|
|
229
|
+
if (this.windowId !== Model.MAIN_WINDOW_ID && LayoutInternal.dragState.mainLayout === this.mainLayout) {
|
|
230
|
+
LayoutInternal.dragState.mainLayout.setDraggingOverWindow(true);
|
|
231
|
+
}
|
|
232
|
+
if (LayoutInternal.dragState.mainLayout !== this.mainLayout) {
|
|
233
|
+
return; // drag not by this layout or its popouts
|
|
234
|
+
}
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
this.dropInfo = undefined;
|
|
237
|
+
const rootdiv = this.selfRef.current;
|
|
238
|
+
this.outlineDiv = this.currentDocument.createElement("div");
|
|
239
|
+
this.outlineDiv.className = this.getClassName(CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
240
|
+
this.outlineDiv.style.visibility = "hidden";
|
|
241
|
+
const speed = this.props.model.getAttribute("tabDragSpeed");
|
|
242
|
+
this.outlineDiv.style.transition = `top ${speed}s, left ${speed}s, width ${speed}s, height ${speed}s`;
|
|
243
|
+
rootdiv.appendChild(this.outlineDiv);
|
|
244
|
+
this.dragging = true;
|
|
245
|
+
this.showOverlay(true);
|
|
246
|
+
// add edge indicators
|
|
247
|
+
if (!this.isDraggingOverWindow && this.props.model.getMaximizedTabset(this.windowId) === undefined) {
|
|
248
|
+
this.setState({ showEdges: this.props.model.isEnableEdgeDock() });
|
|
249
|
+
}
|
|
250
|
+
const clientRect = (_a = this.selfRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
251
|
+
const r = new Rect(event.clientX - (clientRect.left), event.clientY - (clientRect.top), 1, 1);
|
|
252
|
+
r.positionElement(this.outlineDiv);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
this.onDragOver = (event) => {
|
|
256
|
+
var _a, _b, _c;
|
|
257
|
+
if (this.dragging && !this.isDraggingOverWindow) {
|
|
258
|
+
// console.log("onDragOver");
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
const clientRect = (_a = this.selfRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
261
|
+
const pos = {
|
|
262
|
+
x: event.clientX - ((_b = clientRect === null || clientRect === void 0 ? void 0 : clientRect.left) !== null && _b !== void 0 ? _b : 0),
|
|
263
|
+
y: event.clientY - ((_c = clientRect === null || clientRect === void 0 ? void 0 : clientRect.top) !== null && _c !== void 0 ? _c : 0),
|
|
264
|
+
};
|
|
265
|
+
this.checkForBorderToShow(pos.x, pos.y);
|
|
266
|
+
let dropInfo = this.props.model.findDropTargetNode(this.windowId, LayoutInternal.dragState.dragNode, pos.x, pos.y);
|
|
267
|
+
if (dropInfo) {
|
|
268
|
+
this.dropInfo = dropInfo;
|
|
269
|
+
if (this.outlineDiv) {
|
|
270
|
+
this.outlineDiv.className = this.getClassName(dropInfo.className);
|
|
271
|
+
dropInfo.rect.positionElement(this.outlineDiv);
|
|
272
|
+
this.outlineDiv.style.visibility = "visible";
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
this.onDragLeave = (event) => {
|
|
278
|
+
// console.log("onDragLeave", this.windowId, this.dragging);
|
|
279
|
+
if (this.dragging) {
|
|
280
|
+
if (this.windowId !== Model.MAIN_WINDOW_ID) {
|
|
281
|
+
LayoutInternal.dragState.mainLayout.setDraggingOverWindow(false);
|
|
282
|
+
}
|
|
283
|
+
this.clearDragLocal();
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
this.onDrop = (event) => {
|
|
287
|
+
// console.log("ondrop", this.windowId, this.dragging, Layout.dragState);
|
|
288
|
+
if (this.dragging) {
|
|
289
|
+
event.preventDefault();
|
|
290
|
+
const dragState = LayoutInternal.dragState;
|
|
291
|
+
if (this.dropInfo) {
|
|
292
|
+
if (dragState.dragJson !== undefined) {
|
|
293
|
+
const newNode = this.doAction(Actions.addNode(dragState.dragJson, this.dropInfo.node.getId(), this.dropInfo.location, this.dropInfo.index));
|
|
294
|
+
if (dragState.fnNewNodeDropped !== undefined) {
|
|
295
|
+
dragState.fnNewNodeDropped(newNode, event);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else if (dragState.dragNode !== undefined) {
|
|
299
|
+
this.doAction(Actions.moveNode(dragState.dragNode.getId(), this.dropInfo.node.getId(), this.dropInfo.location, this.dropInfo.index));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
this.mainLayout.clearDragMain();
|
|
303
|
+
}
|
|
304
|
+
this.dragEnterCount = 0; // must set to zero here ref sublayouts
|
|
305
|
+
};
|
|
306
|
+
this.orderedTabIds = [];
|
|
307
|
+
this.orderedTabMoveableIds = [];
|
|
308
|
+
this.selfRef = React.createRef();
|
|
309
|
+
this.moveablesRef = React.createRef();
|
|
310
|
+
this.mainRef = React.createRef();
|
|
311
|
+
this.findBorderBarSizeRef = React.createRef();
|
|
312
|
+
this.supportsPopout = props.supportsPopout !== undefined ? props.supportsPopout : defaultSupportsPopout;
|
|
313
|
+
this.popoutURL = props.popoutURL ? props.popoutURL : "popout.html";
|
|
314
|
+
this.icons = Object.assign(Object.assign({}, defaultIcons), props.icons);
|
|
315
|
+
this.windowId = props.windowId ? props.windowId : Model.MAIN_WINDOW_ID;
|
|
316
|
+
this.mainLayout = this.props.mainLayout ? this.props.mainLayout : this;
|
|
317
|
+
this.isDraggingOverWindow = false;
|
|
318
|
+
this.layoutWindow = this.props.model.getwindowsMap().get(this.windowId);
|
|
319
|
+
this.layoutWindow.layout = this;
|
|
320
|
+
this.popoutWindowName = this.props.popoutWindowName || "Popout Window";
|
|
321
|
+
// this.renderCount = 0;
|
|
322
|
+
this.state = {
|
|
323
|
+
rect: Rect.empty(),
|
|
324
|
+
editingTab: undefined,
|
|
325
|
+
showEdges: false,
|
|
326
|
+
showOverlay: false,
|
|
327
|
+
calculatedBorderBarSize: 29,
|
|
328
|
+
layoutRevision: 0,
|
|
329
|
+
forceRevision: 0,
|
|
330
|
+
showHiddenBorder: DockLocation.CENTER
|
|
331
|
+
};
|
|
332
|
+
this.isMainWindow = this.windowId === Model.MAIN_WINDOW_ID;
|
|
333
|
+
}
|
|
334
|
+
componentDidMount() {
|
|
335
|
+
this.updateRect();
|
|
336
|
+
this.currentDocument = this.selfRef.current.ownerDocument;
|
|
337
|
+
this.currentWindow = this.currentDocument.defaultView;
|
|
338
|
+
this.layoutWindow.window = this.currentWindow;
|
|
339
|
+
this.layoutWindow.toScreenRectFunction = (r) => this.getScreenRect(r);
|
|
340
|
+
this.resizeObserver = new ResizeObserver(entries => {
|
|
341
|
+
requestAnimationFrame(() => {
|
|
342
|
+
this.updateRect();
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
if (this.selfRef.current) {
|
|
346
|
+
this.resizeObserver.observe(this.selfRef.current);
|
|
347
|
+
}
|
|
348
|
+
if (this.isMainWindow) {
|
|
349
|
+
this.props.model.addChangeListener(this.onModelChange);
|
|
350
|
+
this.updateLayoutMetrics();
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
// since resizeObserver doesn't always work as expected when observing element in another document
|
|
354
|
+
this.currentWindow.addEventListener("resize", () => {
|
|
355
|
+
this.updateRect();
|
|
356
|
+
});
|
|
357
|
+
const sourceElement = this.props.mainLayout.getRootDiv();
|
|
358
|
+
const targetElement = this.selfRef.current;
|
|
359
|
+
copyInlineStyles(sourceElement, targetElement);
|
|
360
|
+
this.styleObserver = new MutationObserver(() => {
|
|
361
|
+
const changed = copyInlineStyles(sourceElement, targetElement);
|
|
362
|
+
if (changed) {
|
|
363
|
+
this.redraw("mutation observer");
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
// Observe changes to the source element's style attribute
|
|
367
|
+
this.styleObserver.observe(sourceElement, { attributeFilter: ['style'] });
|
|
368
|
+
}
|
|
369
|
+
// allow tabs to overlay when hidden
|
|
370
|
+
document.addEventListener('visibilitychange', () => {
|
|
371
|
+
for (const [_, layoutWindow] of this.props.model.getwindowsMap()) {
|
|
372
|
+
const layout = layoutWindow.layout;
|
|
373
|
+
if (layout) {
|
|
374
|
+
this.redraw("visibility change");
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
componentDidUpdate() {
|
|
380
|
+
this.currentDocument = this.selfRef.current.ownerDocument;
|
|
381
|
+
this.currentWindow = this.currentDocument.defaultView;
|
|
382
|
+
if (this.isMainWindow) {
|
|
383
|
+
if (this.props.model !== this.previousModel) {
|
|
384
|
+
if (this.previousModel !== undefined) {
|
|
385
|
+
this.previousModel.removeChangeListener(this.onModelChange); // stop listening to old model
|
|
386
|
+
}
|
|
387
|
+
this.props.model.getwindowsMap().get(this.windowId).layout = this;
|
|
388
|
+
this.props.model.addChangeListener(this.onModelChange);
|
|
389
|
+
this.layoutWindow = this.props.model.getwindowsMap().get(this.windowId);
|
|
390
|
+
this.layoutWindow.layout = this;
|
|
391
|
+
this.layoutWindow.toScreenRectFunction = (r) => this.getScreenRect(r);
|
|
392
|
+
this.previousModel = this.props.model;
|
|
393
|
+
this.tidyMoveablesMap();
|
|
394
|
+
}
|
|
395
|
+
this.updateLayoutMetrics();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
componentWillUnmount() {
|
|
399
|
+
var _a, _b;
|
|
400
|
+
if (this.selfRef.current) {
|
|
401
|
+
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.unobserve(this.selfRef.current);
|
|
402
|
+
}
|
|
403
|
+
(_b = this.styleObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
404
|
+
}
|
|
405
|
+
render() {
|
|
406
|
+
// console.log("render", this.windowId, this.state.revision, this.renderCount++);
|
|
407
|
+
// first render will be used to find the size (via selfRef)
|
|
408
|
+
if (!this.selfRef.current) {
|
|
409
|
+
return (_jsxs("div", { ref: this.selfRef, className: this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT), children: [_jsx("div", { ref: this.moveablesRef, className: this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_MOVEABLES) }, "__moveables__"), this.renderMetricsElements()] }));
|
|
410
|
+
}
|
|
411
|
+
const model = this.props.model;
|
|
412
|
+
model.getRoot(this.windowId).calcMinMaxSize();
|
|
413
|
+
model.getRoot(this.windowId).setPaths("");
|
|
414
|
+
model.getBorderSet().setPaths();
|
|
415
|
+
const inner = this.renderLayout();
|
|
416
|
+
const outer = this.renderBorders(inner);
|
|
417
|
+
const tabs = this.renderTabs();
|
|
418
|
+
const reorderedTabs = this.reorderComponents(tabs, this.orderedTabIds);
|
|
419
|
+
let floatingWindows = null;
|
|
420
|
+
let reorderedTabMoveables = null;
|
|
421
|
+
let tabStamps = null;
|
|
422
|
+
let metricElements = null;
|
|
423
|
+
if (this.isMainWindow) {
|
|
424
|
+
floatingWindows = this.renderWindows();
|
|
425
|
+
metricElements = this.renderMetricsElements();
|
|
426
|
+
const tabMoveables = this.renderTabMoveables();
|
|
427
|
+
reorderedTabMoveables = this.reorderComponents(tabMoveables, this.orderedTabMoveableIds);
|
|
428
|
+
tabStamps = _jsx("div", { className: this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_TAB_STAMPS), children: this.renderTabStamps() }, "__tabStamps__");
|
|
429
|
+
}
|
|
430
|
+
return (_jsxs("div", { ref: this.selfRef, className: this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT), onDragEnter: this.onDragEnterRaw, onDragLeave: this.onDragLeaveRaw, onDragOver: this.onDragOver, onDrop: this.onDrop, children: [_jsx("div", { ref: this.moveablesRef, className: this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_MOVEABLES) }, "__moveables__"), metricElements, _jsx(Overlay, { layout: this, show: this.state.showOverlay }, "__overlay__"), outer, reorderedTabs, reorderedTabMoveables, tabStamps, this.state.portal, floatingWindows] }));
|
|
431
|
+
}
|
|
432
|
+
renderBorders(inner) {
|
|
433
|
+
const classMain = this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_MAIN);
|
|
434
|
+
const borders = this.props.model.getBorderSet().getBorderMap();
|
|
435
|
+
if (this.isMainWindow && borders.size > 0) {
|
|
436
|
+
inner = (_jsx("div", { className: classMain, ref: this.mainRef, children: inner }));
|
|
437
|
+
const borderSetComponents = new Map();
|
|
438
|
+
const borderSetContentComponents = new Map();
|
|
439
|
+
for (const [_, location] of DockLocation.values) {
|
|
440
|
+
const border = borders.get(location);
|
|
441
|
+
const showBorder = border && border.isShowing() && (!border.isAutoHide() ||
|
|
442
|
+
(border.isAutoHide() && (border.getChildren().length > 0 || this.state.showHiddenBorder === location)));
|
|
443
|
+
if (showBorder) {
|
|
444
|
+
borderSetComponents.set(location, _jsx(BorderTabSet, { layout: this, border: border, size: this.state.calculatedBorderBarSize }));
|
|
445
|
+
borderSetContentComponents.set(location, _jsx(BorderTab, { layout: this, border: border, show: border.getSelected() !== -1 }));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const classBorderOuter = this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_BORDER_CONTAINER);
|
|
449
|
+
const classBorderInner = this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_BORDER_CONTAINER_INNER);
|
|
450
|
+
if (this.props.model.getBorderSet().getLayoutHorizontal()) {
|
|
451
|
+
const innerWithBorderTabs = (_jsxs("div", { className: classBorderInner, style: { flexDirection: "column" }, children: [borderSetContentComponents.get(DockLocation.TOP), _jsxs("div", { className: classBorderInner, style: { flexDirection: "row" }, children: [borderSetContentComponents.get(DockLocation.LEFT), inner, borderSetContentComponents.get(DockLocation.RIGHT)] }), borderSetContentComponents.get(DockLocation.BOTTOM)] }));
|
|
452
|
+
return (_jsxs("div", { className: classBorderOuter, style: { flexDirection: "column" }, children: [borderSetComponents.get(DockLocation.TOP), _jsxs("div", { className: classBorderInner, style: { flexDirection: "row" }, children: [borderSetComponents.get(DockLocation.LEFT), innerWithBorderTabs, borderSetComponents.get(DockLocation.RIGHT)] }), borderSetComponents.get(DockLocation.BOTTOM)] }));
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
const innerWithBorderTabs = (_jsxs("div", { className: classBorderInner, style: { flexDirection: "row" }, children: [borderSetContentComponents.get(DockLocation.LEFT), _jsxs("div", { className: classBorderInner, style: { flexDirection: "column" }, children: [borderSetContentComponents.get(DockLocation.TOP), inner, borderSetContentComponents.get(DockLocation.BOTTOM)] }), borderSetContentComponents.get(DockLocation.RIGHT)] }));
|
|
456
|
+
return (_jsxs("div", { className: classBorderOuter, style: { flexDirection: "row" }, children: [borderSetComponents.get(DockLocation.LEFT), _jsxs("div", { className: classBorderInner, style: { flexDirection: "column" }, children: [borderSetComponents.get(DockLocation.TOP), innerWithBorderTabs, borderSetComponents.get(DockLocation.BOTTOM)] }), borderSetComponents.get(DockLocation.RIGHT)] }));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
else { // no borders
|
|
460
|
+
return (_jsx("div", { className: classMain, ref: this.mainRef, style: { position: "absolute", top: 0, left: 0, bottom: 0, right: 0, display: "flex" }, children: inner }));
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
renderLayout() {
|
|
464
|
+
return (_jsxs(_Fragment, { children: [_jsx(Row, { layout: this, node: this.props.model.getRoot(this.windowId) }, "__row__"), this.renderEdgeIndicators()] }));
|
|
465
|
+
}
|
|
466
|
+
renderEdgeIndicators() {
|
|
467
|
+
const edges = [];
|
|
468
|
+
const arrowIcon = this.icons.edgeArrow;
|
|
469
|
+
if (this.state.showEdges) {
|
|
470
|
+
const r = this.props.model.getRoot(this.windowId).getRect();
|
|
471
|
+
const length = edgeRectLength;
|
|
472
|
+
const width = edgeRectWidth;
|
|
473
|
+
const offset = edgeRectLength / 2;
|
|
474
|
+
const className = this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT);
|
|
475
|
+
const radius = 50;
|
|
476
|
+
edges.push(_jsx("div", { style: { top: 0, left: r.width / 2 - offset, width: length, height: width, borderBottomLeftRadius: radius, borderBottomRightRadius: radius }, className: className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_TOP), children: _jsx("div", { style: { transform: "rotate(180deg)" }, children: arrowIcon }) }, "North"));
|
|
477
|
+
edges.push(_jsx("div", { style: { top: r.height / 2 - offset, left: 0, width: width, height: length, borderTopRightRadius: radius, borderBottomRightRadius: radius }, className: className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_LEFT), children: _jsx("div", { style: { transform: "rotate(90deg)" }, children: arrowIcon }) }, "West"));
|
|
478
|
+
edges.push(_jsx("div", { style: { top: r.height - width, left: r.width / 2 - offset, width: length, height: width, borderTopLeftRadius: radius, borderTopRightRadius: radius }, className: className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_BOTTOM), children: _jsx("div", { children: arrowIcon }) }, "South"));
|
|
479
|
+
edges.push(_jsx("div", { style: { top: r.height / 2 - offset, left: r.width - width, width: width, height: length, borderTopLeftRadius: radius, borderBottomLeftRadius: radius }, className: className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_RIGHT), children: _jsx("div", { style: { transform: "rotate(-90deg)" }, children: arrowIcon }) }, "East"));
|
|
480
|
+
}
|
|
481
|
+
return edges;
|
|
482
|
+
}
|
|
483
|
+
renderWindows() {
|
|
484
|
+
const floatingWindows = [];
|
|
485
|
+
if (this.supportsPopout) {
|
|
486
|
+
const windows = this.props.model.getwindowsMap();
|
|
487
|
+
let i = 1;
|
|
488
|
+
for (const [windowId, layoutWindow] of windows) {
|
|
489
|
+
if (windowId !== Model.MAIN_WINDOW_ID) {
|
|
490
|
+
floatingWindows.push(_jsx(PopoutWindow, { layout: this, title: this.popoutWindowName + " " + i, layoutWindow: layoutWindow, url: this.popoutURL + "?id=" + windowId, onSetWindow: this.onSetWindow, onCloseWindow: this.onCloseWindow, children: _jsx("div", { className: this.props.popoutClassName, children: _jsx(LayoutInternal, Object.assign({}, this.props, { windowId: windowId, mainLayout: this })) }) }, windowId));
|
|
491
|
+
i++;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return floatingWindows;
|
|
496
|
+
}
|
|
497
|
+
renderTabMoveables() {
|
|
498
|
+
// const tabMoveables: React.ReactNode[] = [];
|
|
499
|
+
const tabMoveables = new Map();
|
|
500
|
+
this.props.model.visitNodes((node) => {
|
|
501
|
+
if (node instanceof TabNode) {
|
|
502
|
+
const child = node;
|
|
503
|
+
const element = this.getMoveableElement(child.getId());
|
|
504
|
+
child.setMoveableElement(element);
|
|
505
|
+
const selected = child.isSelected();
|
|
506
|
+
const rect = child.getParent().getContentRect();
|
|
507
|
+
// only render first time if size >0
|
|
508
|
+
const renderTab = child.isRendered() ||
|
|
509
|
+
((selected || !child.isEnableRenderOnDemand()) && (rect.width > 0 && rect.height > 0));
|
|
510
|
+
if (renderTab) {
|
|
511
|
+
// console.log("rendertab", child.getName(), this.props.renderRevision);
|
|
512
|
+
const key = child.getId() + (child.isEnableWindowReMount() ? child.getWindowId() : "");
|
|
513
|
+
tabMoveables.set(node.getId(), createPortal(_jsx(SizeTracker, { rect: rect, selected: child.isSelected(), forceRevision: this.state.forceRevision, tabsRevision: this.props.renderRevision, children: _jsx(ErrorBoundary, { message: this.i18nName(I18nLabel.Error_rendering_component), children: this.props.factory(child) }) }, key), element, key));
|
|
514
|
+
child.setRendered(renderTab);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
return tabMoveables;
|
|
519
|
+
}
|
|
520
|
+
renderTabStamps() {
|
|
521
|
+
const tabStamps = [];
|
|
522
|
+
this.props.model.visitNodes((node) => {
|
|
523
|
+
if (node instanceof TabNode) {
|
|
524
|
+
const child = node;
|
|
525
|
+
// what the tab should look like when dragged (since images need to have been loaded before drag image can be taken)
|
|
526
|
+
tabStamps.push(_jsx(DragContainer, { layout: this, node: child }, child.getId()));
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
return tabStamps;
|
|
530
|
+
}
|
|
531
|
+
renderTabs() {
|
|
532
|
+
const tabs = new Map();
|
|
533
|
+
this.props.model.visitWindowNodes(this.windowId, (node) => {
|
|
534
|
+
if (node instanceof TabNode) {
|
|
535
|
+
const child = node;
|
|
536
|
+
const selected = child.isSelected();
|
|
537
|
+
const path = child.getPath();
|
|
538
|
+
const renderTab = child.isRendered() || selected || !child.isEnableRenderOnDemand();
|
|
539
|
+
if (renderTab) {
|
|
540
|
+
// const rect = (child.getParent() as BorderNode | TabSetNode).getContentRect();
|
|
541
|
+
// const key = child.getId();
|
|
542
|
+
tabs.set(child.getId(), (
|
|
543
|
+
// <SizeTracker rect={rect} forceRevision={this.state.forceRevision} key={key}>
|
|
544
|
+
_jsx(Tab, { layout: this, path: path, node: child, selected: selected }, child.getId())
|
|
545
|
+
// </SizeTracker>
|
|
546
|
+
));
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
return tabs;
|
|
551
|
+
}
|
|
552
|
+
renderMetricsElements() {
|
|
553
|
+
return (_jsx("div", { ref: this.findBorderBarSizeRef, className: this.getClassName(CLASSES.FLEXLAYOUT__BORDER_SIZER), children: "FindBorderBarSize" }, "findBorderBarSize"));
|
|
554
|
+
}
|
|
555
|
+
checkForBorderToShow(x, y) {
|
|
556
|
+
const r = this.getBoundingClientRect(this.mainRef.current);
|
|
557
|
+
const c = r.getCenter();
|
|
558
|
+
const margin = edgeRectWidth;
|
|
559
|
+
const offset = edgeRectLength / 2;
|
|
560
|
+
let overEdge = false;
|
|
561
|
+
if (this.props.model.isEnableEdgeDock() && this.state.showHiddenBorder === DockLocation.CENTER) {
|
|
562
|
+
if ((y > c.y - offset && y < c.y + offset) ||
|
|
563
|
+
(x > c.x - offset && x < c.x + offset)) {
|
|
564
|
+
overEdge = true;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
let location = DockLocation.CENTER;
|
|
568
|
+
if (!overEdge) {
|
|
569
|
+
if (x <= r.x + margin) {
|
|
570
|
+
location = DockLocation.LEFT;
|
|
571
|
+
}
|
|
572
|
+
else if (x >= r.getRight() - margin) {
|
|
573
|
+
location = DockLocation.RIGHT;
|
|
574
|
+
}
|
|
575
|
+
else if (y <= r.y + margin) {
|
|
576
|
+
location = DockLocation.TOP;
|
|
577
|
+
}
|
|
578
|
+
else if (y >= r.getBottom() - margin) {
|
|
579
|
+
location = DockLocation.BOTTOM;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (location !== this.state.showHiddenBorder) {
|
|
583
|
+
this.setState({ showHiddenBorder: location });
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
tidyMoveablesMap() {
|
|
587
|
+
// console.log("tidyMoveablesMap");
|
|
588
|
+
const tabs = new Map();
|
|
589
|
+
this.props.model.visitNodes((node, _) => {
|
|
590
|
+
if (node instanceof TabNode) {
|
|
591
|
+
tabs.set(node.getId(), node);
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
for (const [nodeId, element] of this.moveableElementMap) {
|
|
595
|
+
if (!tabs.has(nodeId)) {
|
|
596
|
+
// console.log("delete", nodeId);
|
|
597
|
+
element.remove(); // remove from dom
|
|
598
|
+
this.moveableElementMap.delete(nodeId); // remove map entry
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
reorderComponents(components, ids) {
|
|
603
|
+
const nextIds = [];
|
|
604
|
+
const nextIdsSet = new Set();
|
|
605
|
+
let reordered = [];
|
|
606
|
+
// Keep any previous tabs in the same DOM order as before, removing any that have been deleted
|
|
607
|
+
for (const id of ids) {
|
|
608
|
+
if (components.get(id)) {
|
|
609
|
+
nextIds.push(id);
|
|
610
|
+
nextIdsSet.add(id);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
ids.splice(0, ids.length, ...nextIds);
|
|
614
|
+
// Add tabs that have been added to the DOM
|
|
615
|
+
for (const [id, _] of components) {
|
|
616
|
+
if (!nextIdsSet.has(id)) {
|
|
617
|
+
ids.push(id);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
reordered = ids.map((id) => {
|
|
621
|
+
return components.get(id);
|
|
622
|
+
});
|
|
623
|
+
return reordered;
|
|
624
|
+
}
|
|
625
|
+
redraw(type) {
|
|
626
|
+
// console.log("redraw", this.windowId, type);
|
|
627
|
+
this.mainLayout.setState((state, props) => { return { forceRevision: state.forceRevision + 1 }; });
|
|
628
|
+
}
|
|
629
|
+
redrawInternal(type) {
|
|
630
|
+
// console.log("redrawInternal", this.windowId, type);
|
|
631
|
+
this.mainLayout.setState((state, props) => { return { layoutRevision: state.layoutRevision + 1 }; });
|
|
632
|
+
}
|
|
633
|
+
doAction(action) {
|
|
634
|
+
if (this.props.onAction !== undefined) {
|
|
635
|
+
const outcome = this.props.onAction(action);
|
|
636
|
+
if (outcome !== undefined) {
|
|
637
|
+
return this.props.model.doAction(outcome);
|
|
638
|
+
}
|
|
639
|
+
return undefined;
|
|
640
|
+
}
|
|
641
|
+
else {
|
|
642
|
+
return this.props.model.doAction(action);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
getBoundingClientRect(div) {
|
|
646
|
+
const layoutRect = this.getDomRect();
|
|
647
|
+
if (layoutRect) {
|
|
648
|
+
return Rect.getBoundingClientRect(div).relativeTo(layoutRect);
|
|
649
|
+
}
|
|
650
|
+
return Rect.empty();
|
|
651
|
+
}
|
|
652
|
+
getMoveableContainer() {
|
|
653
|
+
return this.moveablesRef.current;
|
|
654
|
+
}
|
|
655
|
+
getMoveableElement(id) {
|
|
656
|
+
let moveableElement = this.moveableElementMap.get(id);
|
|
657
|
+
if (moveableElement === undefined) {
|
|
658
|
+
moveableElement = document.createElement("div");
|
|
659
|
+
this.moveablesRef.current.appendChild(moveableElement);
|
|
660
|
+
moveableElement.className = CLASSES.FLEXLAYOUT__TAB_MOVEABLE;
|
|
661
|
+
this.moveableElementMap.set(id, moveableElement);
|
|
662
|
+
}
|
|
663
|
+
return moveableElement;
|
|
664
|
+
}
|
|
665
|
+
getMainLayout() {
|
|
666
|
+
return this.mainLayout;
|
|
667
|
+
}
|
|
668
|
+
getCurrentDocument() {
|
|
669
|
+
return this.currentDocument;
|
|
670
|
+
}
|
|
671
|
+
getDomRect() {
|
|
672
|
+
if (this.selfRef.current) {
|
|
673
|
+
return Rect.fromDomRect(this.selfRef.current.getBoundingClientRect());
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
return Rect.empty();
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
getWindowId() {
|
|
680
|
+
return this.windowId;
|
|
681
|
+
}
|
|
682
|
+
getRootDiv() {
|
|
683
|
+
return this.selfRef.current;
|
|
684
|
+
}
|
|
685
|
+
getMainElement() {
|
|
686
|
+
return this.mainRef.current;
|
|
687
|
+
}
|
|
688
|
+
getFactory() {
|
|
689
|
+
return this.props.factory;
|
|
690
|
+
}
|
|
691
|
+
isSupportsPopout() {
|
|
692
|
+
return this.supportsPopout;
|
|
693
|
+
}
|
|
694
|
+
isRealtimeResize() {
|
|
695
|
+
var _a;
|
|
696
|
+
return (_a = this.props.realtimeResize) !== null && _a !== void 0 ? _a : false;
|
|
697
|
+
}
|
|
698
|
+
getPopoutURL() {
|
|
699
|
+
return this.popoutURL;
|
|
700
|
+
}
|
|
701
|
+
setEditingTab(tabNode) {
|
|
702
|
+
this.setState({ editingTab: tabNode });
|
|
703
|
+
}
|
|
704
|
+
getEditingTab() {
|
|
705
|
+
return this.state.editingTab;
|
|
706
|
+
}
|
|
707
|
+
getModel() {
|
|
708
|
+
return this.props.model;
|
|
709
|
+
}
|
|
710
|
+
getScreenRect(inRect) {
|
|
711
|
+
const rect = inRect.clone();
|
|
712
|
+
const layoutRect = this.getDomRect();
|
|
713
|
+
// Note: outerHeight can be less than innerHeight when window is zoomed, so cannot use
|
|
714
|
+
// const navHeight = Math.min(65, this.currentWindow!.outerHeight - this.currentWindow!.innerHeight);
|
|
715
|
+
// const navWidth = Math.min(65, this.currentWindow!.outerWidth - this.currentWindow!.innerWidth);
|
|
716
|
+
const navHeight = 60;
|
|
717
|
+
const navWidth = 2;
|
|
718
|
+
// console.log(rect.y, this.currentWindow!.screenX,layoutRect.y);
|
|
719
|
+
rect.x = this.currentWindow.screenX + this.currentWindow.scrollX + navWidth / 2 + layoutRect.x + rect.x;
|
|
720
|
+
rect.y = this.currentWindow.screenY + this.currentWindow.scrollY + (navHeight - navWidth / 2) + layoutRect.y + rect.y;
|
|
721
|
+
rect.height += navHeight;
|
|
722
|
+
rect.width += navWidth;
|
|
723
|
+
return rect;
|
|
724
|
+
}
|
|
725
|
+
addTabToTabSet(tabsetId, json) {
|
|
726
|
+
const tabsetNode = this.props.model.getNodeById(tabsetId);
|
|
727
|
+
if (tabsetNode !== undefined) {
|
|
728
|
+
const node = this.doAction(Actions.addNode(json, tabsetId, DockLocation.CENTER, -1));
|
|
729
|
+
return node;
|
|
730
|
+
}
|
|
731
|
+
return undefined;
|
|
732
|
+
}
|
|
733
|
+
addTabToActiveTabSet(json) {
|
|
734
|
+
const tabsetNode = this.props.model.getActiveTabset(this.windowId);
|
|
735
|
+
if (tabsetNode !== undefined) {
|
|
736
|
+
const node = this.doAction(Actions.addNode(json, tabsetNode.getId(), DockLocation.CENTER, -1));
|
|
737
|
+
return node;
|
|
738
|
+
}
|
|
739
|
+
return undefined;
|
|
740
|
+
}
|
|
741
|
+
maximize(tabsetNode) {
|
|
742
|
+
this.doAction(Actions.maximizeToggle(tabsetNode.getId(), this.getWindowId()));
|
|
743
|
+
}
|
|
744
|
+
customizeTab(tabNode, renderValues) {
|
|
745
|
+
if (this.props.onRenderTab) {
|
|
746
|
+
this.props.onRenderTab(tabNode, renderValues);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
customizeTabSet(tabSetNode, renderValues) {
|
|
750
|
+
if (this.props.onRenderTabSet) {
|
|
751
|
+
this.props.onRenderTabSet(tabSetNode, renderValues);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
i18nName(id, param) {
|
|
755
|
+
let message;
|
|
756
|
+
if (this.props.i18nMapper) {
|
|
757
|
+
message = this.props.i18nMapper(id, param);
|
|
758
|
+
}
|
|
759
|
+
if (message === undefined) {
|
|
760
|
+
message = id + (param === undefined ? "" : param);
|
|
761
|
+
}
|
|
762
|
+
return message;
|
|
763
|
+
}
|
|
764
|
+
getShowOverflowMenu() {
|
|
765
|
+
return this.props.onShowOverflowMenu;
|
|
766
|
+
}
|
|
767
|
+
getTabSetPlaceHolderCallback() {
|
|
768
|
+
return this.props.onTabSetPlaceHolder;
|
|
769
|
+
}
|
|
770
|
+
showContextMenu(node, event) {
|
|
771
|
+
if (this.props.onContextMenu) {
|
|
772
|
+
this.props.onContextMenu(node, event);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
auxMouseClick(node, event) {
|
|
776
|
+
if (this.props.onAuxMouseClick) {
|
|
777
|
+
this.props.onAuxMouseClick(node, event);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
showOverlay(show) {
|
|
781
|
+
this.setState({ showOverlay: show });
|
|
782
|
+
enablePointerOnIFrames(!show, this.currentDocument);
|
|
783
|
+
}
|
|
784
|
+
// *************************** Start Drag Drop *************************************
|
|
785
|
+
addTabWithDragAndDrop(event, json, onDrop) {
|
|
786
|
+
const tempNode = TabNode.fromJson(json, this.props.model, false);
|
|
787
|
+
LayoutInternal.dragState = new DragState(this.mainLayout, DragSource.Add, tempNode, json, onDrop);
|
|
788
|
+
}
|
|
789
|
+
moveTabWithDragAndDrop(event, node) {
|
|
790
|
+
this.setDragNode(event, node);
|
|
791
|
+
}
|
|
792
|
+
setDragComponent(event, component, x, y) {
|
|
793
|
+
let dragElement = (_jsx("div", { style: { position: "unset" }, className: this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT) + " " + this.getClassName(CLASSES.FLEXLAYOUT__DRAG_RECT), children: component }));
|
|
794
|
+
const tempDiv = this.currentDocument.createElement('div');
|
|
795
|
+
tempDiv.setAttribute("data-layout-path", "/drag-rectangle");
|
|
796
|
+
tempDiv.style.position = "absolute";
|
|
797
|
+
tempDiv.style.left = "-10000px";
|
|
798
|
+
tempDiv.style.top = "-10000px";
|
|
799
|
+
this.currentDocument.body.appendChild(tempDiv);
|
|
800
|
+
createRoot(tempDiv).render(dragElement);
|
|
801
|
+
event.dataTransfer.setDragImage(tempDiv, x, y);
|
|
802
|
+
setTimeout(() => {
|
|
803
|
+
this.currentDocument.body.removeChild(tempDiv);
|
|
804
|
+
}, 0);
|
|
805
|
+
}
|
|
806
|
+
setDraggingOverWindow(overWindow) {
|
|
807
|
+
// console.log("setDraggingOverWindow", overWindow);
|
|
808
|
+
if (this.isDraggingOverWindow !== overWindow) {
|
|
809
|
+
if (this.outlineDiv) {
|
|
810
|
+
this.outlineDiv.style.visibility = overWindow ? "hidden" : "visible";
|
|
811
|
+
}
|
|
812
|
+
if (overWindow) {
|
|
813
|
+
this.setState({ showEdges: false });
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
// add edge indicators
|
|
817
|
+
if (this.props.model.getMaximizedTabset(this.windowId) === undefined) {
|
|
818
|
+
this.setState({ showEdges: this.props.model.isEnableEdgeDock() });
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
this.isDraggingOverWindow = overWindow;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
clearDragMain() {
|
|
825
|
+
// console.log("clear drag main");
|
|
826
|
+
LayoutInternal.dragState = undefined;
|
|
827
|
+
if (this.windowId === Model.MAIN_WINDOW_ID) {
|
|
828
|
+
this.isDraggingOverWindow = false;
|
|
829
|
+
}
|
|
830
|
+
for (const [, layoutWindow] of this.props.model.getwindowsMap()) {
|
|
831
|
+
// console.log(layoutWindow);
|
|
832
|
+
layoutWindow.layout.clearDragLocal();
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
clearDragLocal() {
|
|
836
|
+
// console.log("clear drag local", this.windowId);
|
|
837
|
+
this.setState({ showEdges: false });
|
|
838
|
+
this.showOverlay(false);
|
|
839
|
+
this.dragEnterCount = 0;
|
|
840
|
+
this.dragging = false;
|
|
841
|
+
if (this.outlineDiv) {
|
|
842
|
+
this.selfRef.current.removeChild(this.outlineDiv);
|
|
843
|
+
this.outlineDiv = undefined;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
LayoutInternal.dragState = undefined;
|
|
848
|
+
export const FlexLayoutVersion = "0.8.11";
|
|
849
|
+
const defaultIcons = {
|
|
850
|
+
close: _jsx(CloseIcon, {}),
|
|
851
|
+
closeTabset: _jsx(CloseIcon, {}),
|
|
852
|
+
popout: _jsx(PopoutIcon, {}),
|
|
853
|
+
maximize: _jsx(MaximizeIcon, {}),
|
|
854
|
+
restore: _jsx(RestoreIcon, {}),
|
|
855
|
+
more: _jsx(OverflowIcon, {}),
|
|
856
|
+
edgeArrow: _jsx(EdgeIcon, {}),
|
|
857
|
+
activeTabset: _jsx(AsterickIcon, {})
|
|
858
|
+
};
|
|
859
|
+
var DragSource;
|
|
860
|
+
(function (DragSource) {
|
|
861
|
+
DragSource["Internal"] = "internal";
|
|
862
|
+
DragSource["External"] = "external";
|
|
863
|
+
DragSource["Add"] = "add";
|
|
864
|
+
})(DragSource || (DragSource = {}));
|
|
865
|
+
/** @internal */
|
|
866
|
+
const defaultSupportsPopout = isDesktop();
|
|
867
|
+
/** @internal */
|
|
868
|
+
const edgeRectLength = 100;
|
|
869
|
+
/** @internal */
|
|
870
|
+
const edgeRectWidth = 10;
|
|
871
|
+
// global layout drag state
|
|
872
|
+
class DragState {
|
|
873
|
+
constructor(mainLayout, dragSource, dragNode, dragJson, fnNewNodeDropped) {
|
|
874
|
+
this.mainLayout = mainLayout;
|
|
875
|
+
this.dragSource = dragSource;
|
|
876
|
+
this.dragNode = dragNode;
|
|
877
|
+
this.dragJson = dragJson;
|
|
878
|
+
this.fnNewNodeDropped = fnNewNodeDropped;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
//# sourceMappingURL=Layout.js.map
|