flexlayout-react 0.5.17 → 0.5.21
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 +20 -0
- package/README.md +123 -104
- package/declarations/Rect.d.ts +4 -0
- package/declarations/Types.d.ts +7 -1
- package/declarations/model/BorderNode.d.ts +1 -0
- package/declarations/model/IJsonModel.d.ts +3 -0
- package/declarations/model/Model.d.ts +1 -0
- package/declarations/view/Layout.d.ts +11 -3
- package/declarations/view/Tab.d.ts +1 -1
- package/dist/flexlayout.js +17 -17
- package/dist/flexlayout_min.js +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 +6 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/BorderNode.js +22 -8
- package/lib/model/BorderNode.js.map +1 -1
- package/lib/model/BorderSet.js +15 -17
- package/lib/model/BorderSet.js.map +1 -1
- package/lib/model/Model.js +21 -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/TabSetNode.js +8 -4
- 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/FloatingWindow.js +13 -5
- package/lib/view/FloatingWindow.js.map +1 -1
- package/lib/view/Layout.js +205 -70
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/Splitter.js +3 -3
- package/lib/view/Splitter.js.map +1 -1
- package/lib/view/Tab.js +18 -7
- package/lib/view/Tab.js.map +1 -1
- package/lib/view/TabButton.js +15 -8
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabFloating.js +29 -15
- package/lib/view/TabFloating.js.map +1 -1
- package/lib/view/TabSet.js +51 -25
- package/lib/view/TabSet.js.map +1 -1
- package/package.json +11 -6
- package/src/PopupMenu.tsx +32 -11
- package/src/Rect.ts +6 -2
- package/src/Types.ts +6 -0
- package/src/model/BorderNode.ts +22 -8
- package/src/model/BorderSet.ts +15 -17
- package/src/model/IJsonModel.ts +3 -0
- package/src/model/Model.ts +28 -3
- package/src/model/RowNode.ts +8 -5
- package/src/model/TabSetNode.ts +8 -4
- package/src/view/BorderButton.tsx +34 -6
- package/src/view/BorderTabSet.tsx +25 -5
- package/src/view/FloatingWindow.tsx +14 -6
- package/src/view/Layout.tsx +271 -92
- package/src/view/Splitter.tsx +4 -1
- package/src/view/Tab.tsx +22 -6
- package/src/view/TabButton.tsx +31 -11
- package/src/view/TabFloating.tsx +47 -23
- package/src/view/TabSet.tsx +72 -20
- package/style/_base.scss +72 -48
- package/style/dark.css +88 -66
- package/style/dark.css.map +1 -1
- package/style/dark.scss +20 -20
- package/style/gray.css +88 -66
- package/style/gray.css.map +1 -1
- package/style/gray.scss +20 -20
- package/style/light.css +88 -66
- package/style/light.css.map +1 -1
- package/style/light.scss +18 -18
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,6 +36,7 @@ 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",
|
|
39
42
|
FLEXLAYOUT__SPLITTER_EXTRA = "flexlayout__splitter_extra",
|
|
@@ -78,4 +81,7 @@ export enum CLASSES {
|
|
|
78
81
|
FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER = "flexlayout__tab_toolbar_sticky_buttons_container",
|
|
79
82
|
FLEXLAYOUT__TAB_TOOLBAR_BUTTON_CLOSE = "flexlayout__tab_toolbar_button-close",
|
|
80
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",
|
|
81
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
|
|
|
@@ -178,7 +180,19 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
178
180
|
}
|
|
179
181
|
|
|
180
182
|
isShowing() {
|
|
181
|
-
|
|
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;
|
|
182
196
|
}
|
|
183
197
|
|
|
184
198
|
/** @hidden @internal */
|
|
@@ -296,18 +310,18 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
296
310
|
childCenter = childRect.x + childRect.width / 2;
|
|
297
311
|
if (x >= pos && x < childCenter) {
|
|
298
312
|
const outlineRect = new Rect(childRect.x - 2, childY, 3, childHeight);
|
|
299
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
313
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
300
314
|
break;
|
|
301
315
|
}
|
|
302
316
|
pos = childCenter;
|
|
303
317
|
}
|
|
304
318
|
if (dropInfo == null) {
|
|
305
319
|
const outlineRect = new Rect(childRect.getRight() - 2, childY, 3, childHeight);
|
|
306
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
320
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
307
321
|
}
|
|
308
322
|
} else {
|
|
309
323
|
const outlineRect = new Rect(this._tabHeaderRect!.x + 1, this._tabHeaderRect!.y + 2, 3, 18);
|
|
310
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0,
|
|
324
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
311
325
|
}
|
|
312
326
|
} else {
|
|
313
327
|
if (this._children.length > 0) {
|
|
@@ -324,18 +338,18 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
324
338
|
childCenter = childRect.y + childRect.height / 2;
|
|
325
339
|
if (y >= pos && y < childCenter) {
|
|
326
340
|
const outlineRect = new Rect(childX, childRect.y - 2, childWidth, 3);
|
|
327
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
341
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
328
342
|
break;
|
|
329
343
|
}
|
|
330
344
|
pos = childCenter;
|
|
331
345
|
}
|
|
332
346
|
if (dropInfo == null) {
|
|
333
347
|
const outlineRect = new Rect(childX, childRect.getBottom() - 2, childWidth, 3);
|
|
334
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
348
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
335
349
|
}
|
|
336
350
|
} else {
|
|
337
351
|
const outlineRect = new Rect(this._tabHeaderRect!.x + 2, this._tabHeaderRect!.y + 1, 18, 3);
|
|
338
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0,
|
|
352
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
339
353
|
}
|
|
340
354
|
}
|
|
341
355
|
if (!dragNode._canDockInto(dragNode, dropInfo)) {
|
|
@@ -343,7 +357,7 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
343
357
|
}
|
|
344
358
|
} else if (this.getSelected() !== -1 && this._contentRect!.contains(x, y)) {
|
|
345
359
|
const outlineRect = this._contentRect;
|
|
346
|
-
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1,
|
|
360
|
+
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
347
361
|
if (!dragNode._canDockInto(dragNode, dropInfo)) {
|
|
348
362
|
return undefined;
|
|
349
363
|
}
|
package/src/model/BorderSet.ts
CHANGED
|
@@ -58,23 +58,21 @@ class BorderSet {
|
|
|
58
58
|
|
|
59
59
|
// sum size of borders to see they will fit
|
|
60
60
|
for (const border of showingBorders) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
adjustableHeight += border.getSize();
|
|
77
|
-
}
|
|
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();
|
|
78
76
|
}
|
|
79
77
|
}
|
|
80
78
|
}
|
package/src/model/IJsonModel.ts
CHANGED
|
@@ -35,10 +35,12 @@ 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
|
|
43
|
+
enableUseVisibility?: boolean; // default: false
|
|
42
44
|
marginInsets?: IInsets; // default: {"top":0,"right":0,"bottom":0,"left":0}
|
|
43
45
|
rootOrientationVertical?: boolean; // default: false
|
|
44
46
|
splitterExtra?: number; // default: 0
|
|
@@ -131,6 +133,7 @@ export interface IBorderAttributes {
|
|
|
131
133
|
barSize?: number; // default: 0 - inherited from global borderBarSize
|
|
132
134
|
className?: string; // - inherited from global borderClassName
|
|
133
135
|
config?: any;
|
|
136
|
+
enableAutoHide?: boolean; // default: false - inherited from global borderEnableAutoHide
|
|
134
137
|
enableDrop?: boolean; // default: true - inherited from global borderEnableDrop
|
|
135
138
|
minSize?: number; // default: 0 - inherited from global borderMinSize
|
|
136
139
|
selected?: number; // default: -1
|
package/src/model/Model.ts
CHANGED
|
@@ -59,6 +59,7 @@ class Model {
|
|
|
59
59
|
attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute.BOOLEAN);
|
|
60
60
|
attributeDefinitions.add("marginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
|
|
61
61
|
.setType("IInsets");
|
|
62
|
+
attributeDefinitions.add("enableUseVisibility", false).setType(Attribute.BOOLEAN);
|
|
62
63
|
|
|
63
64
|
// tab
|
|
64
65
|
attributeDefinitions.add("tabEnableClose", true).setType(Attribute.BOOLEAN);
|
|
@@ -102,6 +103,8 @@ class Model {
|
|
|
102
103
|
attributeDefinitions.add("borderAutoSelectTabWhenOpen", true).setType(Attribute.BOOLEAN);
|
|
103
104
|
attributeDefinitions.add("borderAutoSelectTabWhenClosed", false).setType(Attribute.BOOLEAN);
|
|
104
105
|
attributeDefinitions.add("borderClassName", undefined).setType(Attribute.STRING);
|
|
106
|
+
attributeDefinitions.add("borderEnableAutoHide", false).setType(Attribute.BOOLEAN);
|
|
107
|
+
|
|
105
108
|
return attributeDefinitions;
|
|
106
109
|
}
|
|
107
110
|
|
|
@@ -127,6 +130,9 @@ class Model {
|
|
|
127
130
|
private _pointerFine: boolean;
|
|
128
131
|
/** @hidden @internal */
|
|
129
132
|
private _onCreateTabSet? : (tabNode?: TabNode) => ITabSetAttributes;
|
|
133
|
+
/** @hidden @internal */
|
|
134
|
+
private _showHiddenBorder: DockLocation;
|
|
135
|
+
|
|
130
136
|
|
|
131
137
|
/**
|
|
132
138
|
* 'private' constructor. Use the static method Model.fromJson(json) to create a model
|
|
@@ -138,6 +144,7 @@ class Model {
|
|
|
138
144
|
this._idMap = {};
|
|
139
145
|
this._borders = new BorderSet(this);
|
|
140
146
|
this._pointerFine = true;
|
|
147
|
+
this._showHiddenBorder = DockLocation.CENTER;
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
/** @hidden @internal */
|
|
@@ -156,6 +163,16 @@ class Model {
|
|
|
156
163
|
}
|
|
157
164
|
}
|
|
158
165
|
|
|
166
|
+
/** @hidden @internal */
|
|
167
|
+
_getShowHiddenBorder() {
|
|
168
|
+
return this._showHiddenBorder;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** @hidden @internal */
|
|
172
|
+
_setShowHiddenBorder(location: DockLocation) {
|
|
173
|
+
this._showHiddenBorder = location;
|
|
174
|
+
}
|
|
175
|
+
|
|
159
176
|
/** @hidden @internal */
|
|
160
177
|
_setActiveTabset(tabsetNode: TabSetNode | undefined) {
|
|
161
178
|
this._activeTabSet = tabsetNode;
|
|
@@ -185,6 +202,10 @@ class Model {
|
|
|
185
202
|
return this._attributes.rootOrientationVertical as boolean;
|
|
186
203
|
}
|
|
187
204
|
|
|
205
|
+
isUseVisibility() {
|
|
206
|
+
return this._attributes.enableUseVisibility as boolean;
|
|
207
|
+
}
|
|
208
|
+
|
|
188
209
|
/**
|
|
189
210
|
* Gets the
|
|
190
211
|
* @returns {BorderSet|*}
|
|
@@ -265,13 +286,17 @@ class Model {
|
|
|
265
286
|
const node = this._idMap[action.data.node];
|
|
266
287
|
|
|
267
288
|
if (node instanceof TabSetNode) {
|
|
268
|
-
// first delete all child tabs
|
|
289
|
+
// first delete all child tabs that are closeable
|
|
269
290
|
const children = [...node.getChildren()];
|
|
270
291
|
children.forEach((child, i) => {
|
|
271
|
-
(child as TabNode).
|
|
292
|
+
if ((child as TabNode).isEnableClose()) {
|
|
293
|
+
(child as TabNode)._delete();
|
|
294
|
+
}
|
|
272
295
|
});
|
|
273
296
|
|
|
274
|
-
node.
|
|
297
|
+
if (node.getChildren().length === 0) {
|
|
298
|
+
node._delete();
|
|
299
|
+
}
|
|
275
300
|
this._tidy();
|
|
276
301
|
}
|
|
277
302
|
break;
|
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) {
|
package/src/model/TabSetNode.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 BorderNode from "./BorderNode";
|
|
8
9
|
import IDraggable from "./IDraggable";
|
|
9
10
|
import IDropTarget from "./IDropTarget";
|
|
@@ -27,6 +28,9 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
27
28
|
newLayoutNode._addChild(child);
|
|
28
29
|
});
|
|
29
30
|
}
|
|
31
|
+
if (newLayoutNode._children.length === 0) {
|
|
32
|
+
newLayoutNode._setSelected(-1);
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
if (json.maximized && json.maximized === true) {
|
|
32
36
|
model._setMaximizedTabset(newLayoutNode);
|
|
@@ -268,11 +272,11 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
268
272
|
if (dragNode === this) {
|
|
269
273
|
const dockLocation = DockLocation.CENTER;
|
|
270
274
|
const outlineRect = this._tabHeaderRect;
|
|
271
|
-
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1,
|
|
275
|
+
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
272
276
|
} else if (this._contentRect!.contains(x, y)) {
|
|
273
277
|
const dockLocation = DockLocation.getLocation(this._contentRect!, x, y);
|
|
274
278
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
275
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
279
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
276
280
|
} else if (this._tabHeaderRect != null && this._tabHeaderRect.contains(x, y)) {
|
|
277
281
|
let r: Rect;
|
|
278
282
|
let yy: number;
|
|
@@ -296,7 +300,7 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
296
300
|
if (x >= p && x < childCenter) {
|
|
297
301
|
const dockLocation = DockLocation.CENTER;
|
|
298
302
|
const outlineRect = new Rect(r.x - 2, yy, 3, h);
|
|
299
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
303
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
300
304
|
break;
|
|
301
305
|
}
|
|
302
306
|
p = childCenter;
|
|
@@ -305,7 +309,7 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
305
309
|
if (dropInfo == null) {
|
|
306
310
|
const dockLocation = DockLocation.CENTER;
|
|
307
311
|
const outlineRect = new Rect(r.getRight() - 2, yy, 3, h);
|
|
308
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
312
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
|
|
@@ -6,6 +6,7 @@ import Rect from "../Rect";
|
|
|
6
6
|
import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
|
|
7
7
|
import { ICloseType } from "../model/ICloseType";
|
|
8
8
|
import { CLASSES } from "../Types";
|
|
9
|
+
import { isAuxMouseEvent } from "./TabSet";
|
|
9
10
|
|
|
10
11
|
/** @hidden @internal */
|
|
11
12
|
export interface IBorderButtonProps {
|
|
@@ -16,16 +17,29 @@ export interface IBorderButtonProps {
|
|
|
16
17
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
17
18
|
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
18
19
|
icons?: IIcons;
|
|
20
|
+
path: string;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
/** @hidden @internal */
|
|
22
24
|
export const BorderButton = (props: IBorderButtonProps) => {
|
|
23
|
-
const { layout, node, selected, border, iconFactory, titleFactory, icons } = props;
|
|
25
|
+
const { layout, node, selected, border, iconFactory, titleFactory, icons, path } = props;
|
|
24
26
|
const selfRef = React.useRef<HTMLDivElement | null>(null);
|
|
25
27
|
|
|
26
28
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (!isAuxMouseEvent(event)) {
|
|
30
|
+
const message = layout.i18nName(I18nLabel.Move_Tab, node.getName());
|
|
31
|
+
props.layout.dragStart(event, message, node, node.isEnableDrag(), onClick, (event2: Event) => undefined);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
36
|
+
if (isAuxMouseEvent(event)) {
|
|
37
|
+
layout.auxMouseClick(node, event);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
42
|
+
layout.showContextMenu(node, event);
|
|
29
43
|
};
|
|
30
44
|
|
|
31
45
|
const onClick = () => {
|
|
@@ -105,7 +119,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
121
|
|
|
108
|
-
if (
|
|
122
|
+
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
109
123
|
leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
|
|
110
124
|
}
|
|
111
125
|
|
|
@@ -122,14 +136,28 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
122
136
|
if (node.isEnableClose()) {
|
|
123
137
|
const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
|
|
124
138
|
buttons.push(
|
|
125
|
-
<div
|
|
139
|
+
<div
|
|
140
|
+
key="close"
|
|
141
|
+
data-layout-path={path + "/button/close"}
|
|
142
|
+
title={closeTitle}
|
|
143
|
+
className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_TRAILING)}
|
|
144
|
+
onMouseDown={onCloseMouseDown}
|
|
145
|
+
onClick={onClose}
|
|
146
|
+
onTouchStart={onCloseMouseDown}>
|
|
126
147
|
{icons?.close}
|
|
127
148
|
</div>
|
|
128
149
|
);
|
|
129
150
|
}
|
|
130
151
|
|
|
131
152
|
return (
|
|
132
|
-
<div ref={selfRef} style={{}} className={classNames}
|
|
153
|
+
<div ref={selfRef} style={{}} className={classNames}
|
|
154
|
+
data-layout-path={path}
|
|
155
|
+
onMouseDown={onMouseDown}
|
|
156
|
+
onClick={onAuxMouseClick}
|
|
157
|
+
onAuxClick={onAuxMouseClick}
|
|
158
|
+
onContextMenu={onContextMenu}
|
|
159
|
+
onTouchStart={onMouseDown}
|
|
160
|
+
title={node.getHelpText()}>
|
|
133
161
|
{leading}
|
|
134
162
|
{content}
|
|
135
163
|
{buttons}
|
|
@@ -10,6 +10,7 @@ import { I18nLabel } from "../I18nLabel";
|
|
|
10
10
|
import { useTabOverflow } from "./TabOverflowHook";
|
|
11
11
|
import Orientation from "../Orientation";
|
|
12
12
|
import { CLASSES } from "../Types";
|
|
13
|
+
import { isAuxMouseEvent } from "./TabSet";
|
|
13
14
|
|
|
14
15
|
/** @hidden @internal */
|
|
15
16
|
export interface IBorderTabSetProps {
|
|
@@ -18,11 +19,12 @@ export interface IBorderTabSetProps {
|
|
|
18
19
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
19
20
|
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
20
21
|
icons?: IIcons;
|
|
22
|
+
path: string;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
/** @hidden @internal */
|
|
24
26
|
export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
25
|
-
const { border, layout, iconFactory, titleFactory, icons } = props;
|
|
27
|
+
const { border, layout, iconFactory, titleFactory, icons, path } = props;
|
|
26
28
|
|
|
27
29
|
const toolbarRef = React.useRef<HTMLDivElement | null>(null);
|
|
28
30
|
const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
|
|
@@ -30,13 +32,24 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
30
32
|
|
|
31
33
|
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
|
|
32
34
|
|
|
35
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
36
|
+
if (isAuxMouseEvent(event)) {
|
|
37
|
+
layout.auxMouseClick(border, event);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
42
|
+
layout.showContextMenu(border, event);
|
|
43
|
+
};
|
|
44
|
+
|
|
33
45
|
const onInterceptMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.MouseEvent<HTMLButtonElement, MouseEvent> | React.TouchEvent<HTMLButtonElement>) => {
|
|
34
46
|
event.stopPropagation();
|
|
35
47
|
};
|
|
36
48
|
|
|
37
|
-
const onOverflowClick = () => {
|
|
49
|
+
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
38
50
|
const element = overflowbuttonRef.current!;
|
|
39
51
|
showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
|
|
52
|
+
event.stopPropagation();
|
|
40
53
|
};
|
|
41
54
|
|
|
42
55
|
const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
|
|
@@ -44,11 +57,12 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
44
57
|
userControlledLeft.current = false;
|
|
45
58
|
};
|
|
46
59
|
|
|
47
|
-
const onFloatTab = () => {
|
|
60
|
+
const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
48
61
|
const selectedTabNode = border.getChildren()[border.getSelected()] as TabNode;
|
|
49
62
|
if (selectedTabNode !== undefined) {
|
|
50
63
|
layout.doAction(Actions.floatTab(selectedTabNode.getId()));
|
|
51
64
|
}
|
|
65
|
+
event.stopPropagation();
|
|
52
66
|
};
|
|
53
67
|
|
|
54
68
|
const cm = layout.getClassName;
|
|
@@ -65,6 +79,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
65
79
|
layout={layout}
|
|
66
80
|
border={border.getLocation().getName()}
|
|
67
81
|
node={child}
|
|
82
|
+
path={path + "/tb" + i}
|
|
68
83
|
key={child.getId()}
|
|
69
84
|
selected={isSelected}
|
|
70
85
|
iconFactory={iconFactory}
|
|
@@ -97,7 +112,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
97
112
|
<button
|
|
98
113
|
key="overflowbutton"
|
|
99
114
|
ref={overflowbuttonRef}
|
|
100
|
-
className={cm(
|
|
115
|
+
className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ + border.getLocation().getName())}
|
|
101
116
|
title={overflowTitle}
|
|
102
117
|
onClick={onOverflowClick}
|
|
103
118
|
onMouseDown={onInterceptMouseDown}
|
|
@@ -145,7 +160,12 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
return (
|
|
148
|
-
<div ref={selfRef} style={style} className={borderClasses}
|
|
163
|
+
<div ref={selfRef} dir="ltr" style={style} className={borderClasses}
|
|
164
|
+
data-layout-path={path}
|
|
165
|
+
onClick={onAuxMouseClick}
|
|
166
|
+
onAuxClick={onAuxMouseClick}
|
|
167
|
+
onContextMenu={onContextMenu}
|
|
168
|
+
onWheel={onMouseWheel}>
|
|
149
169
|
<div style={{ height: borderHeight }} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}>
|
|
150
170
|
<div style={innerStyle} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}>
|
|
151
171
|
{tabs}
|