flexlayout-react 0.5.16 → 0.5.20
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 +24 -0
- package/README.md +128 -97
- package/declarations/DragDrop.d.ts +1 -0
- package/declarations/Rect.d.ts +4 -0
- package/declarations/Types.d.ts +8 -1
- package/declarations/model/BorderNode.d.ts +2 -1
- package/declarations/model/IJsonModel.d.ts +8 -0
- package/declarations/model/Model.d.ts +1 -0
- package/declarations/view/Layout.d.ts +19 -6
- package/dist/flexlayout.js +19 -19
- package/dist/flexlayout_min.js +1 -1
- package/lib/DockLocation.js +25 -11
- package/lib/DockLocation.js.map +1 -1
- package/lib/DragDrop.js +19 -3
- package/lib/DragDrop.js.map +1 -1
- package/lib/PopupMenu.js +14 -9
- package/lib/PopupMenu.js.map +1 -1
- package/lib/Rect.js +3 -0
- package/lib/Rect.js.map +1 -1
- package/lib/Types.js +7 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/BorderNode.js +61 -14
- package/lib/model/BorderNode.js.map +1 -1
- package/lib/model/BorderSet.js +33 -19
- package/lib/model/BorderSet.js.map +1 -1
- package/lib/model/Model.js +23 -3
- package/lib/model/Model.js.map +1 -1
- package/lib/model/RowNode.js +19 -5
- package/lib/model/RowNode.js.map +1 -1
- package/lib/model/TabNode.js +10 -0
- package/lib/model/TabNode.js.map +1 -1
- package/lib/model/TabSetNode.js +34 -19
- package/lib/model/TabSetNode.js.map +1 -1
- package/lib/view/BorderButton.js +17 -6
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTabSet.js +17 -6
- package/lib/view/BorderTabSet.js.map +1 -1
- package/lib/view/Layout.js +232 -57
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/Splitter.js +35 -4
- package/lib/view/Splitter.js.map +1 -1
- package/lib/view/Tab.js +2 -2
- package/lib/view/Tab.js.map +1 -1
- package/lib/view/TabButton.js +16 -7
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabFloating.js +24 -12
- package/lib/view/TabFloating.js.map +1 -1
- package/lib/view/TabSet.js +49 -24
- package/lib/view/TabSet.js.map +1 -1
- package/package.json +11 -6
- package/src/DockLocation.ts +30 -9
- package/src/DragDrop.ts +26 -3
- package/src/PopupMenu.tsx +32 -11
- package/src/Rect.ts +6 -2
- package/src/Types.ts +7 -0
- package/src/model/BorderNode.ts +57 -15
- package/src/model/BorderSet.ts +32 -19
- package/src/model/IJsonModel.ts +8 -0
- package/src/model/Model.ts +30 -3
- package/src/model/RowNode.ts +8 -5
- package/src/model/TabNode.ts +11 -0
- package/src/model/TabSetNode.ts +33 -19
- package/src/view/BorderButton.tsx +34 -6
- package/src/view/BorderTabSet.tsx +25 -5
- package/src/view/Layout.tsx +299 -82
- package/src/view/Splitter.tsx +53 -4
- package/src/view/Tab.tsx +8 -2
- package/src/view/TabButton.tsx +31 -7
- package/src/view/TabFloating.tsx +42 -20
- package/src/view/TabSet.tsx +70 -18
- package/style/_base.scss +78 -51
- package/style/dark.css +94 -68
- package/style/dark.css.map +1 -1
- package/style/dark.scss +20 -20
- package/style/gray.css +94 -68
- package/style/gray.css.map +1 -1
- package/style/gray.scss +20 -20
- package/style/light.css +94 -68
- package/style/light.css.map +1 -1
- package/style/light.scss +18 -18
- package/yarn-error.log +0 -11828
package/src/DragDrop.ts
CHANGED
|
@@ -23,6 +23,10 @@ class DragDrop {
|
|
|
23
23
|
/** @hidden @internal */
|
|
24
24
|
private _glass: HTMLDivElement | undefined;
|
|
25
25
|
/** @hidden @internal */
|
|
26
|
+
private _defaultGlassCursor: string;
|
|
27
|
+
/** @hidden @internal */
|
|
28
|
+
private _glassCursorOverride: string | undefined;
|
|
29
|
+
/** @hidden @internal */
|
|
26
30
|
private _manualGlassManagement: boolean = false;
|
|
27
31
|
/** @hidden @internal */
|
|
28
32
|
private _lastClick: number;
|
|
@@ -59,6 +63,8 @@ class DragDrop {
|
|
|
59
63
|
this._glass.style.outline = "none";
|
|
60
64
|
}
|
|
61
65
|
|
|
66
|
+
this._defaultGlassCursor = "default";
|
|
67
|
+
|
|
62
68
|
this._onMouseMove = this._onMouseMove.bind(this);
|
|
63
69
|
this._onMouseUp = this._onMouseUp.bind(this);
|
|
64
70
|
this._onKeyPress = this._onKeyPress.bind(this);
|
|
@@ -111,9 +117,26 @@ class DragDrop {
|
|
|
111
117
|
this._glassShowing = false;
|
|
112
118
|
this._document = undefined;
|
|
113
119
|
this._rootElement = undefined;
|
|
120
|
+
this.setGlassCursorOverride(undefined);
|
|
114
121
|
}
|
|
115
122
|
}
|
|
116
123
|
|
|
124
|
+
/** @hidden @internal */
|
|
125
|
+
_updateGlassCursor() {
|
|
126
|
+
this._glass!.style.cursor = this._glassCursorOverride ?? this._defaultGlassCursor;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** @hidden @internal */
|
|
130
|
+
_setDefaultGlassCursor(cursor: string) {
|
|
131
|
+
this._defaultGlassCursor = cursor;
|
|
132
|
+
this._updateGlassCursor()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
setGlassCursorOverride(cursor: string | undefined) {
|
|
136
|
+
this._glassCursorOverride = cursor;
|
|
137
|
+
this._updateGlassCursor()
|
|
138
|
+
}
|
|
139
|
+
|
|
117
140
|
startDrag(
|
|
118
141
|
event: Event | React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement> | React.DragEvent<Element> | undefined,
|
|
119
142
|
fDragStart: ((pos: { clientX: number; clientY: number }) => boolean) | undefined,
|
|
@@ -154,14 +177,14 @@ class DragDrop {
|
|
|
154
177
|
this._startX = posEvent.clientX;
|
|
155
178
|
this._startY = posEvent.clientY;
|
|
156
179
|
if (!window.matchMedia || window.matchMedia("(pointer: fine)").matches) {
|
|
157
|
-
this.
|
|
180
|
+
this._setDefaultGlassCursor(getComputedStyle(event.target as Element).cursor);
|
|
158
181
|
}
|
|
159
182
|
this._stopPropagation(event);
|
|
160
183
|
this._preventDefault(event);
|
|
161
184
|
} else {
|
|
162
185
|
this._startX = 0;
|
|
163
186
|
this._startY = 0;
|
|
164
|
-
this.
|
|
187
|
+
this._setDefaultGlassCursor("default");
|
|
165
188
|
}
|
|
166
189
|
|
|
167
190
|
this._dragging = false;
|
|
@@ -274,7 +297,7 @@ class DragDrop {
|
|
|
274
297
|
if (!this._dragging && (Math.abs(this._startX - posEvent.clientX) > 5 || Math.abs(this._startY - posEvent.clientY) > 5)) {
|
|
275
298
|
this._dragging = true;
|
|
276
299
|
if (this._fDragStart) {
|
|
277
|
-
this.
|
|
300
|
+
this._setDefaultGlassCursor("move");
|
|
278
301
|
this._dragging = this._fDragStart({ clientX: this._startX, clientY: this._startY });
|
|
279
302
|
}
|
|
280
303
|
}
|
package/src/PopupMenu.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as ReactDOM from "react-dom";
|
|
3
|
+
import { DragDrop } from ".";
|
|
3
4
|
import TabNode from "./model/TabNode";
|
|
5
|
+
import { CLASSES } from "./Types";
|
|
4
6
|
|
|
5
7
|
/** @hidden @internal */
|
|
6
8
|
export function showPopup(
|
|
@@ -15,7 +17,7 @@ export function showPopup(
|
|
|
15
17
|
const layoutRect = layoutDiv.getBoundingClientRect();
|
|
16
18
|
|
|
17
19
|
const elm = currentDocument.createElement("div");
|
|
18
|
-
elm.className = classNameMapper(
|
|
20
|
+
elm.className = classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_CONTAINER);
|
|
19
21
|
if (triggerRect.left < layoutRect.left + layoutRect.width / 2) {
|
|
20
22
|
elm.style.left = triggerRect.left - layoutRect.left + "px";
|
|
21
23
|
} else {
|
|
@@ -27,27 +29,37 @@ export function showPopup(
|
|
|
27
29
|
} else {
|
|
28
30
|
elm.style.bottom = layoutRect.bottom - triggerRect.bottom + "px";
|
|
29
31
|
}
|
|
32
|
+
DragDrop.instance.addGlass(() => onHide());
|
|
33
|
+
DragDrop.instance.setGlassCursorOverride("default");
|
|
34
|
+
|
|
30
35
|
layoutDiv.appendChild(elm);
|
|
31
36
|
|
|
32
37
|
const onHide = () => {
|
|
38
|
+
DragDrop.instance.hideGlass();
|
|
33
39
|
layoutDiv.removeChild(elm);
|
|
34
40
|
ReactDOM.unmountComponentAtNode(elm);
|
|
35
|
-
elm.removeEventListener("
|
|
36
|
-
currentDocument.removeEventListener("
|
|
41
|
+
elm.removeEventListener("mousedown", onElementMouseDown);
|
|
42
|
+
currentDocument.removeEventListener("mousedown", onDocMouseDown);
|
|
37
43
|
};
|
|
38
44
|
|
|
39
|
-
const
|
|
45
|
+
const onElementMouseDown = (event: Event) => {
|
|
40
46
|
event.stopPropagation();
|
|
41
47
|
};
|
|
42
48
|
|
|
43
|
-
const
|
|
49
|
+
const onDocMouseDown = (event: Event) => {
|
|
44
50
|
onHide();
|
|
45
51
|
};
|
|
46
52
|
|
|
47
|
-
elm.addEventListener("
|
|
48
|
-
currentDocument.addEventListener("
|
|
53
|
+
elm.addEventListener("mousedown", onElementMouseDown);
|
|
54
|
+
currentDocument.addEventListener("mousedown", onDocMouseDown);
|
|
49
55
|
|
|
50
|
-
ReactDOM.render(<PopupMenu
|
|
56
|
+
ReactDOM.render(<PopupMenu
|
|
57
|
+
currentDocument={currentDocument}
|
|
58
|
+
onSelect={onSelect}
|
|
59
|
+
onHide={onHide}
|
|
60
|
+
items={items}
|
|
61
|
+
classNameMapper={classNameMapper}
|
|
62
|
+
/>, elm);
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
/** @hidden @internal */
|
|
@@ -69,11 +81,20 @@ const PopupMenu = (props: IPopupMenuProps) => {
|
|
|
69
81
|
event.stopPropagation();
|
|
70
82
|
};
|
|
71
83
|
|
|
72
|
-
const itemElements = items.map((item) => (
|
|
73
|
-
<div key={item.index}
|
|
84
|
+
const itemElements = items.map((item, i) => (
|
|
85
|
+
<div key={item.index}
|
|
86
|
+
className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_ITEM)}
|
|
87
|
+
data-layout-path={"/popup-menu/tb" + i}
|
|
88
|
+
onClick={(event) => onItemClick(item, event)}
|
|
89
|
+
title={item.node.getHelpText()}>
|
|
74
90
|
{item.node._getRenderedName()}
|
|
75
91
|
</div>
|
|
76
92
|
));
|
|
77
93
|
|
|
78
|
-
return
|
|
94
|
+
return (
|
|
95
|
+
<div className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU)}
|
|
96
|
+
data-layout-path="/popup-menu"
|
|
97
|
+
>
|
|
98
|
+
{itemElements}
|
|
99
|
+
</div>);
|
|
79
100
|
};
|
package/src/Rect.ts
CHANGED
|
@@ -18,8 +18,8 @@ class Rect {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
static fromElement(element: Element) {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let { x, y, width, height } = element.getBoundingClientRect();
|
|
22
|
+
return new Rect(x, y, width, height);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
clone() {
|
|
@@ -42,6 +42,10 @@ class Rect {
|
|
|
42
42
|
return this.x + this.width;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
getCenter() {
|
|
46
|
+
return { x: this.x + this.width / 2, y: this.y + this.height / 2 };
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
positionElement(element: HTMLElement, position?: string) {
|
|
46
50
|
this.styleWithPosition(element.style, position);
|
|
47
51
|
}
|
package/src/Types.ts
CHANGED
|
@@ -9,6 +9,8 @@ export enum CLASSES {
|
|
|
9
9
|
FLEXLAYOUT__BORDER_BUTTON_TRAILING = "flexlayout__border_button_trailing",
|
|
10
10
|
FLEXLAYOUT__BORDER_BUTTON__SELECTED = "flexlayout__border_button--selected",
|
|
11
11
|
FLEXLAYOUT__BORDER_BUTTON__UNSELECTED = "flexlayout__border_button--unselected",
|
|
12
|
+
FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW = "flexlayout__border_toolbar_button_overflow",
|
|
13
|
+
FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ = "flexlayout__border_toolbar_button_overflow_",
|
|
12
14
|
|
|
13
15
|
FLEXLAYOUT__BORDER_INNER = "flexlayout__border_inner",
|
|
14
16
|
FLEXLAYOUT__BORDER_INNER_ = "flexlayout__border_inner_",
|
|
@@ -34,8 +36,10 @@ export enum CLASSES {
|
|
|
34
36
|
FLEXLAYOUT__LAYOUT = "flexlayout__layout",
|
|
35
37
|
|
|
36
38
|
FLEXLAYOUT__OUTLINE_RECT = "flexlayout__outline_rect",
|
|
39
|
+
FLEXLAYOUT__OUTLINE_RECT_EDGE = "flexlayout__outline_rect_edge",
|
|
37
40
|
|
|
38
41
|
FLEXLAYOUT__SPLITTER = "flexlayout__splitter",
|
|
42
|
+
FLEXLAYOUT__SPLITTER_EXTRA = "flexlayout__splitter_extra",
|
|
39
43
|
FLEXLAYOUT__SPLITTER_ = "flexlayout__splitter_",
|
|
40
44
|
FLEXLAYOUT__SPLITTER_BORDER = "flexlayout__splitter_border",
|
|
41
45
|
FLEXLAYOUT__SPLITTER_DRAG = "flexlayout__splitter_drag",
|
|
@@ -77,4 +81,7 @@ export enum CLASSES {
|
|
|
77
81
|
FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER = "flexlayout__tab_toolbar_sticky_buttons_container",
|
|
78
82
|
FLEXLAYOUT__TAB_TOOLBAR_BUTTON_CLOSE = "flexlayout__tab_toolbar_button-close",
|
|
79
83
|
|
|
84
|
+
FLEXLAYOUT__POPUP_MENU_CONTAINER = "flexlayout__popup_menu_container",
|
|
85
|
+
FLEXLAYOUT__POPUP_MENU_ITEM = "flexlayout__popup_menu_item",
|
|
86
|
+
FLEXLAYOUT__POPUP_MENU = "flexlayout__popup_menu",
|
|
80
87
|
}
|
package/src/model/BorderNode.ts
CHANGED
|
@@ -4,6 +4,7 @@ import DockLocation from "../DockLocation";
|
|
|
4
4
|
import DropInfo from "../DropInfo";
|
|
5
5
|
import Orientation from "../Orientation";
|
|
6
6
|
import Rect from "../Rect";
|
|
7
|
+
import { CLASSES } from "../Types";
|
|
7
8
|
import IDraggable from "./IDraggable";
|
|
8
9
|
import IDropTarget from "./IDropTarget";
|
|
9
10
|
import { IJsonBorderNode } from "./IJsonModel";
|
|
@@ -50,6 +51,7 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
50
51
|
attributeDefinitions.addInherited("autoSelectTabWhenClosed", "borderAutoSelectTabWhenClosed").setType(Attribute.BOOLEAN);
|
|
51
52
|
attributeDefinitions.addInherited("size", "borderSize").setType(Attribute.NUMBER);
|
|
52
53
|
attributeDefinitions.addInherited("minSize", "borderMinSize").setType(Attribute.NUMBER);
|
|
54
|
+
attributeDefinitions.addInherited("enableAutoHide", "borderEnableAutoHide").setType(Attribute.BOOLEAN);
|
|
53
55
|
return attributeDefinitions;
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -128,7 +130,19 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
128
130
|
}
|
|
129
131
|
|
|
130
132
|
getSize() {
|
|
131
|
-
|
|
133
|
+
const defaultSize = this._getAttr("size") as number;
|
|
134
|
+
const selected = this.getSelected();
|
|
135
|
+
if (selected === -1) {
|
|
136
|
+
return defaultSize;
|
|
137
|
+
} else {
|
|
138
|
+
const tabNode = this._children[selected] as TabNode;
|
|
139
|
+
const tabBorderSize = (this._location._orientation === Orientation.HORZ) ? tabNode._getAttr("borderWidth") : tabNode._getAttr("borderHeight");
|
|
140
|
+
if (tabBorderSize === -1) {
|
|
141
|
+
return defaultSize;
|
|
142
|
+
} else {
|
|
143
|
+
return tabBorderSize;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
132
146
|
}
|
|
133
147
|
|
|
134
148
|
getMinSize() {
|
|
@@ -157,7 +171,7 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
157
171
|
* this.state.model.doAction(
|
|
158
172
|
* FlexLayout.Actions.updateNodeAttributes(node.getId(), {config:myConfigObject}));
|
|
159
173
|
*/
|
|
160
|
-
|
|
174
|
+
getConfig() {
|
|
161
175
|
return this._attributes.config;
|
|
162
176
|
}
|
|
163
177
|
|
|
@@ -166,7 +180,19 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
166
180
|
}
|
|
167
181
|
|
|
168
182
|
isShowing() {
|
|
169
|
-
|
|
183
|
+
const show = this._attributes.show as boolean;
|
|
184
|
+
if (show) {
|
|
185
|
+
if (this._model._getShowHiddenBorder() !== this._location && this.isAutoHide() && this._children.length === 0) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
return true;
|
|
189
|
+
} else {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
isAutoHide() {
|
|
195
|
+
return this._getAttr("enableAutoHide") as boolean;
|
|
170
196
|
}
|
|
171
197
|
|
|
172
198
|
/** @hidden @internal */
|
|
@@ -176,7 +202,22 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
176
202
|
|
|
177
203
|
/** @hidden @internal */
|
|
178
204
|
_setSize(pos: number) {
|
|
179
|
-
|
|
205
|
+
const selected = this.getSelected();
|
|
206
|
+
if (selected === -1) {
|
|
207
|
+
this._attributes.size = pos;
|
|
208
|
+
} else {
|
|
209
|
+
const tabNode = this._children[selected] as TabNode;
|
|
210
|
+
const tabBorderSize = (this._location._orientation === Orientation.HORZ) ? tabNode._getAttr("borderWidth") : tabNode._getAttr("borderHeight");
|
|
211
|
+
if (tabBorderSize === -1) {
|
|
212
|
+
this._attributes.size = pos;
|
|
213
|
+
} else {
|
|
214
|
+
if (this._location._orientation === Orientation.HORZ) {
|
|
215
|
+
tabNode._setBorderWidth(pos);
|
|
216
|
+
} else {
|
|
217
|
+
tabNode._setBorderHeight(pos);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
180
221
|
}
|
|
181
222
|
|
|
182
223
|
/** @hidden @internal */
|
|
@@ -269,18 +310,18 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
269
310
|
childCenter = childRect.x + childRect.width / 2;
|
|
270
311
|
if (x >= pos && x < childCenter) {
|
|
271
312
|
const outlineRect = new Rect(childRect.x - 2, childY, 3, childHeight);
|
|
272
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
313
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
273
314
|
break;
|
|
274
315
|
}
|
|
275
316
|
pos = childCenter;
|
|
276
317
|
}
|
|
277
318
|
if (dropInfo == null) {
|
|
278
319
|
const outlineRect = new Rect(childRect.getRight() - 2, childY, 3, childHeight);
|
|
279
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
320
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
280
321
|
}
|
|
281
322
|
} else {
|
|
282
323
|
const outlineRect = new Rect(this._tabHeaderRect!.x + 1, this._tabHeaderRect!.y + 2, 3, 18);
|
|
283
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0,
|
|
324
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
284
325
|
}
|
|
285
326
|
} else {
|
|
286
327
|
if (this._children.length > 0) {
|
|
@@ -297,18 +338,18 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
297
338
|
childCenter = childRect.y + childRect.height / 2;
|
|
298
339
|
if (y >= pos && y < childCenter) {
|
|
299
340
|
const outlineRect = new Rect(childX, childRect.y - 2, childWidth, 3);
|
|
300
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
341
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
301
342
|
break;
|
|
302
343
|
}
|
|
303
344
|
pos = childCenter;
|
|
304
345
|
}
|
|
305
346
|
if (dropInfo == null) {
|
|
306
347
|
const outlineRect = new Rect(childX, childRect.getBottom() - 2, childWidth, 3);
|
|
307
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
348
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
308
349
|
}
|
|
309
350
|
} else {
|
|
310
351
|
const outlineRect = new Rect(this._tabHeaderRect!.x + 2, this._tabHeaderRect!.y + 1, 18, 3);
|
|
311
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0,
|
|
352
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
312
353
|
}
|
|
313
354
|
}
|
|
314
355
|
if (!dragNode._canDockInto(dragNode, dropInfo)) {
|
|
@@ -316,7 +357,7 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
316
357
|
}
|
|
317
358
|
} else if (this.getSelected() !== -1 && this._contentRect!.contains(x, y)) {
|
|
318
359
|
const outlineRect = this._contentRect;
|
|
319
|
-
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1,
|
|
360
|
+
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
320
361
|
if (!dragNode._canDockInto(dragNode, dropInfo)) {
|
|
321
362
|
return undefined;
|
|
322
363
|
}
|
|
@@ -370,18 +411,19 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
370
411
|
const minSize = useMinSize ? this.getMinSize() : 0;
|
|
371
412
|
const outerRect = this._model._getOuterInnerRects().outer;
|
|
372
413
|
const innerRect = this._model._getOuterInnerRects().inner;
|
|
414
|
+
const rootRow = this._model.getRoot();
|
|
373
415
|
if (this._location === DockLocation.TOP) {
|
|
374
416
|
pBounds[0] = outerRect.y + minSize;
|
|
375
|
-
pBounds[1] = innerRect.getBottom() - splitter.getHeight();
|
|
417
|
+
pBounds[1] = Math.max(pBounds[0], innerRect.getBottom() - splitter.getHeight() - rootRow.getMinHeight());
|
|
376
418
|
} else if (this._location === DockLocation.LEFT) {
|
|
377
419
|
pBounds[0] = outerRect.x + minSize;
|
|
378
|
-
pBounds[1] = innerRect.getRight() - splitter.getWidth();
|
|
420
|
+
pBounds[1] = Math.max(pBounds[0], innerRect.getRight() - splitter.getWidth() - rootRow.getMinWidth());
|
|
379
421
|
} else if (this._location === DockLocation.BOTTOM) {
|
|
380
|
-
pBounds[0] = innerRect.y;
|
|
381
422
|
pBounds[1] = outerRect.getBottom() - splitter.getHeight() - minSize;
|
|
423
|
+
pBounds[0] = Math.min(pBounds[1], innerRect.y + rootRow.getMinHeight());
|
|
382
424
|
} else if (this._location === DockLocation.RIGHT) {
|
|
383
|
-
pBounds[0] = innerRect.x;
|
|
384
425
|
pBounds[1] = outerRect.getRight() - splitter.getWidth() - minSize;
|
|
426
|
+
pBounds[0] = Math.min(pBounds[1], innerRect.x + rootRow.getMinWidth());
|
|
385
427
|
}
|
|
386
428
|
return pBounds;
|
|
387
429
|
}
|
package/src/model/BorderSet.ts
CHANGED
|
@@ -46,8 +46,9 @@ class BorderSet {
|
|
|
46
46
|
/** @hidden @internal */
|
|
47
47
|
_layoutBorder(outerInnerRects: { inner: Rect; outer: Rect }, metrics: ILayoutMetrics) {
|
|
48
48
|
const rect = outerInnerRects.outer;
|
|
49
|
-
const
|
|
50
|
-
|
|
49
|
+
const rootRow = this._model.getRoot();
|
|
50
|
+
let height = Math.max(0, rect.height - rootRow.getMinHeight());
|
|
51
|
+
let width = Math.max(0, rect.width - rootRow.getMinWidth());
|
|
51
52
|
let sumHeight = 0;
|
|
52
53
|
let sumWidth = 0;
|
|
53
54
|
let adjustableHeight = 0;
|
|
@@ -57,43 +58,55 @@ class BorderSet {
|
|
|
57
58
|
|
|
58
59
|
// sum size of borders to see they will fit
|
|
59
60
|
for (const border of showingBorders) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
border._setAdjustedSize(border.getSize());
|
|
62
|
+
const visible = border.getSelected() !== -1;
|
|
63
|
+
if (border.getLocation().getOrientation() === Orientation.HORZ) {
|
|
64
|
+
sumWidth += border.getBorderBarSize() ;
|
|
65
|
+
if (visible) {
|
|
66
|
+
width -= this._model.getSplitterSize();
|
|
67
|
+
sumWidth += border.getSize();
|
|
68
|
+
adjustableWidth += border.getSize();
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
sumHeight += border.getBorderBarSize();
|
|
72
|
+
if (visible) {
|
|
73
|
+
height -= this._model.getSplitterSize();
|
|
74
|
+
sumHeight += border.getSize();
|
|
75
|
+
adjustableHeight += border.getSize();
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
// adjust border sizes if too large
|
|
80
81
|
let j = 0;
|
|
82
|
+
let adjusted = false;
|
|
81
83
|
while ((sumWidth > width && adjustableWidth > 0) || (sumHeight > height && adjustableHeight > 0)) {
|
|
82
84
|
const border = showingBorders[j];
|
|
83
85
|
if (border.getSelected() !== -1) {
|
|
84
86
|
// visible
|
|
85
87
|
const size = border._getAdjustedSize();
|
|
86
|
-
if (sumWidth > width && adjustableWidth > 0 && border.getLocation().getOrientation() === Orientation.HORZ && size > 0
|
|
88
|
+
if (sumWidth > width && adjustableWidth > 0 && border.getLocation().getOrientation() === Orientation.HORZ && size > 0
|
|
89
|
+
&& size > border.getMinSize()) {
|
|
87
90
|
border._setAdjustedSize(size - 1);
|
|
88
91
|
sumWidth--;
|
|
89
92
|
adjustableWidth--;
|
|
90
|
-
|
|
93
|
+
adjusted = true;
|
|
94
|
+
} else if (sumHeight > height && adjustableHeight > 0 && border.getLocation().getOrientation() === Orientation.VERT && size > 0
|
|
95
|
+
&& size > border.getMinSize()) {
|
|
91
96
|
border._setAdjustedSize(size - 1);
|
|
92
97
|
sumHeight--;
|
|
93
98
|
adjustableHeight--;
|
|
99
|
+
adjusted = true;
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
102
|
j = (j + 1) % showingBorders.length;
|
|
103
|
+
if (j===0) {
|
|
104
|
+
if (adjusted) {
|
|
105
|
+
adjusted = false;
|
|
106
|
+
} else {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
97
110
|
}
|
|
98
111
|
|
|
99
112
|
showingBorders.forEach((border) => {
|
package/src/model/IJsonModel.ts
CHANGED
|
@@ -35,13 +35,17 @@ export interface IGlobalAttributes {
|
|
|
35
35
|
borderAutoSelectTabWhenOpen?: boolean; // default: true
|
|
36
36
|
borderBarSize?: number; // default: 0
|
|
37
37
|
borderClassName?: string;
|
|
38
|
+
borderEnableAutoHide?: boolean; // default: false
|
|
38
39
|
borderEnableDrop?: boolean; // default: true
|
|
39
40
|
borderMinSize?: number; // default: 0
|
|
40
41
|
borderSize?: number; // default: 200
|
|
41
42
|
enableEdgeDock?: boolean; // default: true
|
|
42
43
|
marginInsets?: IInsets; // default: {"top":0,"right":0,"bottom":0,"left":0}
|
|
43
44
|
rootOrientationVertical?: boolean; // default: false
|
|
45
|
+
splitterExtra?: number; // default: 0
|
|
44
46
|
splitterSize?: number; // default: -1
|
|
47
|
+
tabBorderHeight?: number; // default: -1
|
|
48
|
+
tabBorderWidth?: number; // default: -1
|
|
45
49
|
tabClassName?: string;
|
|
46
50
|
tabCloseType?: ICloseType; // default: 1
|
|
47
51
|
tabDragSpeed?: number; // default: 0.3
|
|
@@ -104,6 +108,8 @@ export interface ITabSetAttributes {
|
|
|
104
108
|
width?: number;
|
|
105
109
|
}
|
|
106
110
|
export interface ITabAttributes {
|
|
111
|
+
borderHeight?: number; // default: -1 - inherited from global tabBorderHeight
|
|
112
|
+
borderWidth?: number; // default: -1 - inherited from global tabBorderWidth
|
|
107
113
|
className?: string; // - inherited from global tabClassName
|
|
108
114
|
closeType?: ICloseType; // default: 1 - inherited from global tabCloseType
|
|
109
115
|
component?: string;
|
|
@@ -114,6 +120,7 @@ export interface ITabAttributes {
|
|
|
114
120
|
enableRename?: boolean; // default: true - inherited from global tabEnableRename
|
|
115
121
|
enableRenderOnDemand?: boolean; // default: true - inherited from global tabEnableRenderOnDemand
|
|
116
122
|
floating?: boolean; // default: false
|
|
123
|
+
helpText?: string;
|
|
117
124
|
icon?: string; // - inherited from global tabIcon
|
|
118
125
|
id?: string;
|
|
119
126
|
name?: string; // default: "[Unnamed Tab]"
|
|
@@ -125,6 +132,7 @@ export interface IBorderAttributes {
|
|
|
125
132
|
barSize?: number; // default: 0 - inherited from global borderBarSize
|
|
126
133
|
className?: string; // - inherited from global borderClassName
|
|
127
134
|
config?: any;
|
|
135
|
+
enableAutoHide?: boolean; // default: false - inherited from global borderEnableAutoHide
|
|
128
136
|
enableDrop?: boolean; // default: true - inherited from global borderEnableDrop
|
|
129
137
|
minSize?: number; // default: 0 - inherited from global borderMinSize
|
|
130
138
|
selected?: number; // default: -1
|
package/src/model/Model.ts
CHANGED
|
@@ -54,6 +54,7 @@ class Model {
|
|
|
54
54
|
const attributeDefinitions = new AttributeDefinitions();
|
|
55
55
|
// splitter
|
|
56
56
|
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
|
|
57
|
+
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);
|
|
57
58
|
attributeDefinitions.add("enableEdgeDock", true).setType(Attribute.BOOLEAN);
|
|
58
59
|
attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute.BOOLEAN);
|
|
59
60
|
attributeDefinitions.add("marginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
|
|
@@ -69,6 +70,8 @@ class Model {
|
|
|
69
70
|
attributeDefinitions.add("tabIcon", undefined).setType(Attribute.STRING);
|
|
70
71
|
attributeDefinitions.add("tabEnableRenderOnDemand", true).setType(Attribute.BOOLEAN);
|
|
71
72
|
attributeDefinitions.add("tabDragSpeed", 0.3).setType(Attribute.NUMBER);
|
|
73
|
+
attributeDefinitions.add("tabBorderWidth", -1).setType(Attribute.NUMBER);
|
|
74
|
+
attributeDefinitions.add("tabBorderHeight", -1).setType(Attribute.NUMBER);
|
|
72
75
|
|
|
73
76
|
// tabset
|
|
74
77
|
attributeDefinitions.add("tabSetEnableDeleteWhenEmpty", true).setType(Attribute.BOOLEAN);
|
|
@@ -99,6 +102,8 @@ class Model {
|
|
|
99
102
|
attributeDefinitions.add("borderAutoSelectTabWhenOpen", true).setType(Attribute.BOOLEAN);
|
|
100
103
|
attributeDefinitions.add("borderAutoSelectTabWhenClosed", false).setType(Attribute.BOOLEAN);
|
|
101
104
|
attributeDefinitions.add("borderClassName", undefined).setType(Attribute.STRING);
|
|
105
|
+
attributeDefinitions.add("borderEnableAutoHide", false).setType(Attribute.BOOLEAN);
|
|
106
|
+
|
|
102
107
|
return attributeDefinitions;
|
|
103
108
|
}
|
|
104
109
|
|
|
@@ -124,6 +129,9 @@ class Model {
|
|
|
124
129
|
private _pointerFine: boolean;
|
|
125
130
|
/** @hidden @internal */
|
|
126
131
|
private _onCreateTabSet? : (tabNode?: TabNode) => ITabSetAttributes;
|
|
132
|
+
/** @hidden @internal */
|
|
133
|
+
private _showHiddenBorder: DockLocation;
|
|
134
|
+
|
|
127
135
|
|
|
128
136
|
/**
|
|
129
137
|
* 'private' constructor. Use the static method Model.fromJson(json) to create a model
|
|
@@ -135,6 +143,7 @@ class Model {
|
|
|
135
143
|
this._idMap = {};
|
|
136
144
|
this._borders = new BorderSet(this);
|
|
137
145
|
this._pointerFine = true;
|
|
146
|
+
this._showHiddenBorder = DockLocation.CENTER;
|
|
138
147
|
}
|
|
139
148
|
|
|
140
149
|
/** @hidden @internal */
|
|
@@ -153,6 +162,16 @@ class Model {
|
|
|
153
162
|
}
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
/** @hidden @internal */
|
|
166
|
+
_getShowHiddenBorder() {
|
|
167
|
+
return this._showHiddenBorder;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** @hidden @internal */
|
|
171
|
+
_setShowHiddenBorder(location: DockLocation) {
|
|
172
|
+
this._showHiddenBorder = location;
|
|
173
|
+
}
|
|
174
|
+
|
|
156
175
|
/** @hidden @internal */
|
|
157
176
|
_setActiveTabset(tabsetNode: TabSetNode | undefined) {
|
|
158
177
|
this._activeTabSet = tabsetNode;
|
|
@@ -262,13 +281,17 @@ class Model {
|
|
|
262
281
|
const node = this._idMap[action.data.node];
|
|
263
282
|
|
|
264
283
|
if (node instanceof TabSetNode) {
|
|
265
|
-
// first delete all child tabs
|
|
284
|
+
// first delete all child tabs that are closeable
|
|
266
285
|
const children = [...node.getChildren()];
|
|
267
286
|
children.forEach((child, i) => {
|
|
268
|
-
(child as TabNode).
|
|
287
|
+
if ((child as TabNode).isEnableClose()) {
|
|
288
|
+
(child as TabNode)._delete();
|
|
289
|
+
}
|
|
269
290
|
});
|
|
270
291
|
|
|
271
|
-
node.
|
|
292
|
+
if (node.getChildren().length === 0) {
|
|
293
|
+
node._delete();
|
|
294
|
+
}
|
|
272
295
|
this._tidy();
|
|
273
296
|
}
|
|
274
297
|
break;
|
|
@@ -420,6 +443,10 @@ class Model {
|
|
|
420
443
|
return splitterSize;
|
|
421
444
|
}
|
|
422
445
|
|
|
446
|
+
getSplitterExtra() {
|
|
447
|
+
return this._attributes.splitterExtra as number;
|
|
448
|
+
}
|
|
449
|
+
|
|
423
450
|
isEnableEdgeDock() {
|
|
424
451
|
return this._attributes.enableEdgeDock as boolean;
|
|
425
452
|
}
|
package/src/model/RowNode.ts
CHANGED
|
@@ -5,6 +5,7 @@ import DockLocation from "../DockLocation";
|
|
|
5
5
|
import DropInfo from "../DropInfo";
|
|
6
6
|
import Orientation from "../Orientation";
|
|
7
7
|
import Rect from "../Rect";
|
|
8
|
+
import { CLASSES } from "../Types";
|
|
8
9
|
import BorderNode from "./BorderNode";
|
|
9
10
|
import IDraggable from "./IDraggable";
|
|
10
11
|
import IDropTarget from "./IDropTarget";
|
|
@@ -381,7 +382,9 @@ class RowNode extends Node implements IDropTarget {
|
|
|
381
382
|
// add tabset into empty root
|
|
382
383
|
if (this === this._model.getRoot() && this._children.length === 0) {
|
|
383
384
|
const callback = this._model._getOnCreateTabSet();
|
|
384
|
-
|
|
385
|
+
let attrs = callback ? callback() : {};
|
|
386
|
+
attrs = {...attrs, selected: -1};
|
|
387
|
+
const child = new TabSetNode(this._model, attrs);
|
|
385
388
|
this._model._setActiveTabset(child);
|
|
386
389
|
this._addChild(child);
|
|
387
390
|
}
|
|
@@ -404,24 +407,24 @@ class RowNode extends Node implements IDropTarget {
|
|
|
404
407
|
const dockLocation = DockLocation.LEFT;
|
|
405
408
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
406
409
|
outlineRect.width = outlineRect.width / 2;
|
|
407
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
410
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
408
411
|
} else if (x > this._rect.getRight() - margin && yy > h / 2 - half && yy < h / 2 + half) {
|
|
409
412
|
const dockLocation = DockLocation.RIGHT;
|
|
410
413
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
411
414
|
outlineRect.width = outlineRect.width / 2;
|
|
412
415
|
outlineRect.x += outlineRect.width;
|
|
413
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
416
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
414
417
|
} else if (y < this._rect.y + margin && xx > w / 2 - half && xx < w / 2 + half) {
|
|
415
418
|
const dockLocation = DockLocation.TOP;
|
|
416
419
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
417
420
|
outlineRect.height = outlineRect.height / 2;
|
|
418
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
421
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
419
422
|
} else if (y > this._rect.getBottom() - margin && xx > w / 2 - half && xx < w / 2 + half) {
|
|
420
423
|
const dockLocation = DockLocation.BOTTOM;
|
|
421
424
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
422
425
|
outlineRect.height = outlineRect.height / 2;
|
|
423
426
|
outlineRect.y += outlineRect.height;
|
|
424
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
427
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
425
428
|
}
|
|
426
429
|
|
|
427
430
|
if (dropInfo !== undefined) {
|