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/view/Splitter.tsx
CHANGED
|
@@ -13,17 +13,19 @@ import { ILayoutCallbacks } from "./Layout";
|
|
|
13
13
|
export interface ISplitterProps {
|
|
14
14
|
layout: ILayoutCallbacks;
|
|
15
15
|
node: SplitterNode;
|
|
16
|
+
path: string;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/** @hidden @internal */
|
|
19
20
|
export const Splitter = (props: ISplitterProps) => {
|
|
20
|
-
const { layout, node } = props;
|
|
21
|
+
const { layout, node, path } = props;
|
|
21
22
|
|
|
22
23
|
const pBounds = React.useRef<number[]>([]);
|
|
23
24
|
const outlineDiv = React.useRef<HTMLDivElement | undefined>(undefined);
|
|
24
25
|
const parentNode = node.getParent() as RowNode | BorderNode;
|
|
25
26
|
|
|
26
27
|
const onMouseDown = (event: Event | React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
28
|
+
DragDrop.instance.setGlassCursorOverride(node.getOrientation() === Orientation.HORZ ? "ns-resize" : "ew-resize");
|
|
27
29
|
DragDrop.instance.startDrag(event, onDragStart, onDragMove, onDragEnd, onDragCancel, undefined, undefined, layout.getCurrentDocument(), layout.getRootDiv());
|
|
28
30
|
pBounds.current = parentNode._getSplitterBounds(node, true);
|
|
29
31
|
const rootdiv = layout.getRootDiv();
|
|
@@ -31,7 +33,14 @@ export const Splitter = (props: ISplitterProps) => {
|
|
|
31
33
|
outlineDiv.current.style.position = "absolute";
|
|
32
34
|
outlineDiv.current.className = layout.getClassName(CLASSES.FLEXLAYOUT__SPLITTER_DRAG);
|
|
33
35
|
outlineDiv.current.style.cursor = node.getOrientation() === Orientation.HORZ ? "ns-resize" : "ew-resize";
|
|
34
|
-
node.getRect()
|
|
36
|
+
const r = node.getRect();
|
|
37
|
+
if (node.getOrientation() === Orientation.VERT && r.width < 2) {
|
|
38
|
+
r.width = 2;
|
|
39
|
+
} else if (node.getOrientation() === Orientation.HORZ && r.height < 2) {
|
|
40
|
+
r.height = 2;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
r.positionElement(outlineDiv.current);
|
|
35
44
|
rootdiv.appendChild(outlineDiv.current);
|
|
36
45
|
};
|
|
37
46
|
|
|
@@ -106,7 +115,8 @@ export const Splitter = (props: ISplitterProps) => {
|
|
|
106
115
|
};
|
|
107
116
|
|
|
108
117
|
const cm = layout.getClassName;
|
|
109
|
-
|
|
118
|
+
let r = node.getRect();
|
|
119
|
+
const style = r.styleWithPosition({
|
|
110
120
|
cursor: node.getOrientation() === Orientation.HORZ ? "ns-resize" : "ew-resize",
|
|
111
121
|
});
|
|
112
122
|
let className = cm(CLASSES.FLEXLAYOUT__SPLITTER) + " " + cm(CLASSES.FLEXLAYOUT__SPLITTER_ + node.getOrientation().getName());
|
|
@@ -119,5 +129,44 @@ export const Splitter = (props: ISplitterProps) => {
|
|
|
119
129
|
}
|
|
120
130
|
}
|
|
121
131
|
|
|
122
|
-
|
|
132
|
+
const extra = node.getModel().getSplitterExtra();
|
|
133
|
+
if (extra === 0) {
|
|
134
|
+
return (<div
|
|
135
|
+
style={style}
|
|
136
|
+
data-layout-path={path}
|
|
137
|
+
className={className}
|
|
138
|
+
onTouchStart={onMouseDown}
|
|
139
|
+
onMouseDown={onMouseDown}>
|
|
140
|
+
</div>);
|
|
141
|
+
} else {
|
|
142
|
+
// add extended transparent div for hit testing
|
|
143
|
+
// extends forward only, so as not to interfere with scrollbars
|
|
144
|
+
let r2 = r.clone();
|
|
145
|
+
r2.x = 0;
|
|
146
|
+
r2.y = 0;
|
|
147
|
+
if (node.getOrientation() === Orientation.VERT) {
|
|
148
|
+
r2.width += extra;
|
|
149
|
+
} else {
|
|
150
|
+
r2.height += extra;
|
|
151
|
+
}
|
|
152
|
+
const style2 = r2.styleWithPosition({
|
|
153
|
+
cursor: node.getOrientation() === Orientation.HORZ ? "ns-resize" : "ew-resize"
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const className2 = cm(CLASSES.FLEXLAYOUT__SPLITTER_EXTRA);
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<div
|
|
160
|
+
style={style}
|
|
161
|
+
data-layout-path={path}
|
|
162
|
+
className={className}>
|
|
163
|
+
<div
|
|
164
|
+
style={style2}
|
|
165
|
+
className={className2}
|
|
166
|
+
onTouchStart={onMouseDown}
|
|
167
|
+
onMouseDown={onMouseDown}>
|
|
168
|
+
</div>
|
|
169
|
+
</div>);
|
|
170
|
+
}
|
|
171
|
+
|
|
123
172
|
};
|
package/src/view/Tab.tsx
CHANGED
|
@@ -15,11 +15,12 @@ export interface ITabProps {
|
|
|
15
15
|
selected: boolean;
|
|
16
16
|
node: TabNode;
|
|
17
17
|
factory: (node: TabNode) => React.ReactNode;
|
|
18
|
+
path: string;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
/** @hidden @internal */
|
|
21
22
|
export const Tab = (props: ITabProps) => {
|
|
22
|
-
const { layout, selected, node, factory } = props;
|
|
23
|
+
const { layout, selected, node, factory, path } = props;
|
|
23
24
|
const [renderComponent, setRenderComponent] = React.useState<boolean>(!props.node.isEnableRenderOnDemand() || props.selected);
|
|
24
25
|
|
|
25
26
|
React.useLayoutEffect(() => {
|
|
@@ -64,7 +65,12 @@ export const Tab = (props: ITabProps) => {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
return (
|
|
67
|
-
<div
|
|
68
|
+
<div
|
|
69
|
+
className={className}
|
|
70
|
+
data-layout-path={path}
|
|
71
|
+
onMouseDown={onMouseDown}
|
|
72
|
+
onTouchStart={onMouseDown}
|
|
73
|
+
style={style}>
|
|
68
74
|
<ErrorBoundary message={props.layout.i18nName(I18nLabel.Error_rendering_component)}>
|
|
69
75
|
<Fragment>{child}</Fragment>
|
|
70
76
|
</ErrorBoundary>
|
package/src/view/TabButton.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import Rect from "../Rect";
|
|
|
7
7
|
import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
|
|
8
8
|
import { ICloseType } from "../model/ICloseType";
|
|
9
9
|
import { CLASSES } from "../Types";
|
|
10
|
+
import { isAuxMouseEvent } from "./TabSet";
|
|
10
11
|
|
|
11
12
|
/** @hidden @internal */
|
|
12
13
|
export interface ITabButtonProps {
|
|
@@ -18,22 +19,34 @@ export interface ITabButtonProps {
|
|
|
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 TabButton = (props: ITabButtonProps) => {
|
|
25
|
-
const { layout, node, show, selected, iconFactory, titleFactory, icons } = props;
|
|
27
|
+
const { layout, node, show, selected, iconFactory, titleFactory, icons, path } = props;
|
|
26
28
|
const selfRef = React.useRef<HTMLDivElement | null>(null);
|
|
27
29
|
const contentRef = React.useRef<HTMLInputElement | null>(null);
|
|
28
30
|
const contentWidth = React.useRef<number>(0);
|
|
29
31
|
|
|
30
32
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
31
|
-
|
|
33
|
+
|
|
34
|
+
if (!isAuxMouseEvent(event) && !layout.getEditingTab()) {
|
|
32
35
|
const message = layout.i18nName(I18nLabel.Move_Tab, node.getName());
|
|
33
36
|
layout.dragStart(event, message, node, node.isEnableDrag(), onClick, onDoubleClick);
|
|
34
37
|
}
|
|
35
38
|
};
|
|
36
39
|
|
|
40
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
41
|
+
if (isAuxMouseEvent(event)) {
|
|
42
|
+
layout.auxMouseClick(node, event);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
47
|
+
layout.showContextMenu(node, event);
|
|
48
|
+
};
|
|
49
|
+
|
|
37
50
|
const onClick = () => {
|
|
38
51
|
layout.doAction(Actions.selectTab(node.getId()));
|
|
39
52
|
};
|
|
@@ -43,7 +56,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
43
56
|
layout.setEditingTab(node);
|
|
44
57
|
layout.getCurrentDocument()!.body.addEventListener("mousedown", onEndEdit);
|
|
45
58
|
layout.getCurrentDocument()!.body.addEventListener("touchstart", onEndEdit);
|
|
46
|
-
}
|
|
59
|
+
}
|
|
47
60
|
// else {
|
|
48
61
|
// const parentNode = node.getParent() as TabSetNode;
|
|
49
62
|
// if (parentNode.canMaximize()) {
|
|
@@ -140,8 +153,8 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
140
153
|
let name = node.getName();
|
|
141
154
|
|
|
142
155
|
function isTitleObject(obj: any): obj is ITitleObject {
|
|
143
|
-
return obj.titleContent !== undefined
|
|
144
|
-
|
|
156
|
+
return obj.titleContent !== undefined
|
|
157
|
+
}
|
|
145
158
|
|
|
146
159
|
if (titleFactory !== undefined) {
|
|
147
160
|
const titleObj = titleFactory(node);
|
|
@@ -158,7 +171,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
158
171
|
}
|
|
159
172
|
}
|
|
160
173
|
|
|
161
|
-
if (
|
|
174
|
+
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
162
175
|
leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
|
|
163
176
|
}
|
|
164
177
|
|
|
@@ -184,6 +197,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
184
197
|
style={contentStyle}
|
|
185
198
|
ref={contentRef}
|
|
186
199
|
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_TEXTBOX)}
|
|
200
|
+
data-layout-path={path + "/textbox"}
|
|
187
201
|
type="text"
|
|
188
202
|
autoFocus={true}
|
|
189
203
|
defaultValue={node.getName()}
|
|
@@ -197,7 +211,13 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
197
211
|
if (node.isEnableClose()) {
|
|
198
212
|
const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
|
|
199
213
|
buttons.push(
|
|
200
|
-
<div
|
|
214
|
+
<div
|
|
215
|
+
key="close"
|
|
216
|
+
data-layout-path={path + "/button/close"}
|
|
217
|
+
title={closeTitle}
|
|
218
|
+
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_TRAILING)}
|
|
219
|
+
onMouseDown={onCloseMouseDown} onClick={onClose}
|
|
220
|
+
onTouchStart={onCloseMouseDown}>
|
|
201
221
|
{icons?.close}
|
|
202
222
|
</div>
|
|
203
223
|
);
|
|
@@ -206,11 +226,15 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
206
226
|
return (
|
|
207
227
|
<div
|
|
208
228
|
ref={selfRef}
|
|
229
|
+
data-layout-path={path}
|
|
209
230
|
style={{
|
|
210
231
|
visibility: show ? "visible" : "hidden",
|
|
211
232
|
}}
|
|
212
233
|
className={classNames}
|
|
213
234
|
onMouseDown={onMouseDown}
|
|
235
|
+
onClick={onAuxMouseClick}
|
|
236
|
+
onAuxClick={onAuxMouseClick}
|
|
237
|
+
onContextMenu={onContextMenu}
|
|
214
238
|
onTouchStart={onMouseDown}
|
|
215
239
|
title={node.getHelpText()}
|
|
216
240
|
>
|
package/src/view/TabFloating.tsx
CHANGED
|
@@ -11,11 +11,22 @@ export interface ITabFloatingProps {
|
|
|
11
11
|
layout: ILayoutCallbacks;
|
|
12
12
|
selected: boolean;
|
|
13
13
|
node: TabNode;
|
|
14
|
+
path: string;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/** @hidden @internal */
|
|
17
18
|
export const TabFloating = (props: ITabFloatingProps) => {
|
|
18
|
-
const { layout, selected, node } = props;
|
|
19
|
+
const { layout, selected, node, path } = props;
|
|
20
|
+
|
|
21
|
+
const showPopout = () => {
|
|
22
|
+
if (node.getWindow()) {
|
|
23
|
+
node.getWindow()!.focus();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const dockPopout = () => {
|
|
28
|
+
layout.doAction(Actions.unFloatTab(node.getId()));
|
|
29
|
+
}
|
|
19
30
|
|
|
20
31
|
const onMouseDown = () => {
|
|
21
32
|
const parent = node.getParent() as TabSetNode;
|
|
@@ -28,14 +39,12 @@ export const TabFloating = (props: ITabFloatingProps) => {
|
|
|
28
39
|
|
|
29
40
|
const onClickFocus = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
|
30
41
|
event.preventDefault();
|
|
31
|
-
|
|
32
|
-
node.getWindow()!.focus();
|
|
33
|
-
}
|
|
42
|
+
showPopout();
|
|
34
43
|
};
|
|
35
44
|
|
|
36
45
|
const onClickDock = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
|
37
46
|
event.preventDefault();
|
|
38
|
-
|
|
47
|
+
dockPopout();
|
|
39
48
|
};
|
|
40
49
|
|
|
41
50
|
const cm = layout.getClassName;
|
|
@@ -48,21 +57,34 @@ export const TabFloating = (props: ITabFloatingProps) => {
|
|
|
48
57
|
const showMessage = layout.i18nName(I18nLabel.Floating_Window_Show_Window);
|
|
49
58
|
const dockMessage = layout.i18nName(I18nLabel.Floating_Window_Dock_Window);
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
const customRenderCallback = layout.getOnRenderFloatingTabPlaceholder();
|
|
61
|
+
if (customRenderCallback) {
|
|
62
|
+
return (
|
|
63
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)} onMouseDown={onMouseDown} onTouchStart={onMouseDown} style={style}>
|
|
64
|
+
{customRenderCallback(dockPopout, showPopout)}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
return (
|
|
69
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)}
|
|
70
|
+
data-layout-path={path}
|
|
71
|
+
onMouseDown={onMouseDown}
|
|
72
|
+
onTouchStart={onMouseDown}
|
|
73
|
+
style={style}>
|
|
74
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING_INNER)}>
|
|
75
|
+
<div>{message}</div>
|
|
76
|
+
<div>
|
|
77
|
+
<a href="#" onClick={onClickFocus}>
|
|
78
|
+
{showMessage}
|
|
79
|
+
</a>
|
|
80
|
+
</div>
|
|
81
|
+
<div>
|
|
82
|
+
<a href="#" onClick={onClickDock}>
|
|
83
|
+
{dockMessage}
|
|
84
|
+
</a>
|
|
85
|
+
</div>
|
|
64
86
|
</div>
|
|
65
87
|
</div>
|
|
66
|
-
|
|
67
|
-
|
|
88
|
+
);
|
|
89
|
+
}
|
|
68
90
|
};
|
package/src/view/TabSet.tsx
CHANGED
|
@@ -17,12 +17,13 @@ export interface ITabSetProps {
|
|
|
17
17
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
18
18
|
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
19
19
|
icons?: IIcons;
|
|
20
|
-
editingTab?: TabNode;
|
|
20
|
+
editingTab?: TabNode;
|
|
21
|
+
path?: string;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/** @hidden @internal */
|
|
24
25
|
export const TabSet = (props: ITabSetProps) => {
|
|
25
|
-
const { node, layout, iconFactory, titleFactory, icons } = props;
|
|
26
|
+
const { node, layout, iconFactory, titleFactory, icons, path } = props;
|
|
26
27
|
|
|
27
28
|
const toolbarRef = React.useRef<HTMLDivElement | null>(null);
|
|
28
29
|
const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
|
|
@@ -31,9 +32,10 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
31
32
|
|
|
32
33
|
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated } = useTabOverflow(node, Orientation.HORZ, toolbarRef, stickyButtonsRef);
|
|
33
34
|
|
|
34
|
-
const onOverflowClick = () => {
|
|
35
|
+
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
35
36
|
const element = overflowbuttonRef.current!;
|
|
36
37
|
showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
|
|
38
|
+
event.stopPropagation();
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
|
|
@@ -42,37 +44,52 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
42
44
|
};
|
|
43
45
|
|
|
44
46
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
name
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if (!isAuxMouseEvent(event)) {
|
|
48
|
+
let name = node.getName();
|
|
49
|
+
if (name === undefined) {
|
|
50
|
+
name = "";
|
|
51
|
+
} else {
|
|
52
|
+
name = ": " + name;
|
|
53
|
+
}
|
|
54
|
+
layout.doAction(Actions.setActiveTabset(node.getId()));
|
|
55
|
+
if (!layout.getEditingTab()) {
|
|
56
|
+
const message = layout.i18nName(I18nLabel.Move_Tabset, name);
|
|
57
|
+
layout.dragStart(event, message, node, node.isEnableDrag(), (event2: Event) => undefined, onDoubleClick);
|
|
58
|
+
}
|
|
50
59
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
63
|
+
if (isAuxMouseEvent(event)) {
|
|
64
|
+
layout.auxMouseClick(node, event);
|
|
55
65
|
}
|
|
56
66
|
};
|
|
57
67
|
|
|
68
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
69
|
+
layout.showContextMenu(node, event);
|
|
70
|
+
};
|
|
71
|
+
|
|
58
72
|
const onInterceptMouseDown = (event: React.MouseEvent | React.TouchEvent) => {
|
|
59
73
|
event.stopPropagation();
|
|
60
74
|
};
|
|
61
75
|
|
|
62
|
-
const onMaximizeToggle = () => {
|
|
76
|
+
const onMaximizeToggle = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
63
77
|
if (node.canMaximize()) {
|
|
64
78
|
layout.maximize(node);
|
|
65
79
|
}
|
|
80
|
+
event.stopPropagation();
|
|
66
81
|
};
|
|
67
82
|
|
|
68
|
-
const onClose = () => {
|
|
83
|
+
const onClose = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
69
84
|
layout.doAction(Actions.deleteTabset(node.getId()));
|
|
85
|
+
event.stopPropagation();
|
|
70
86
|
};
|
|
71
87
|
|
|
72
|
-
const onFloatTab = () => {
|
|
88
|
+
const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
73
89
|
if (selectedTabNode !== undefined) {
|
|
74
90
|
layout.doAction(Actions.floatTab(selectedTabNode.getId()));
|
|
75
91
|
}
|
|
92
|
+
event.stopPropagation();
|
|
76
93
|
};
|
|
77
94
|
|
|
78
95
|
const onDoubleClick = (event: Event) => {
|
|
@@ -105,6 +122,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
105
122
|
<TabButton
|
|
106
123
|
layout={layout}
|
|
107
124
|
node={child}
|
|
125
|
+
path={path + "/tb" + i}
|
|
108
126
|
key={child.getId()}
|
|
109
127
|
selected={isSelected}
|
|
110
128
|
show={true}
|
|
@@ -153,6 +171,8 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
153
171
|
buttons.push(
|
|
154
172
|
<button
|
|
155
173
|
key="overflowbutton"
|
|
174
|
+
data-layout-path={path + "/button/overflow"}
|
|
175
|
+
|
|
156
176
|
ref={overflowbuttonRef}
|
|
157
177
|
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_OVERFLOW)}
|
|
158
178
|
title={overflowTitle}
|
|
@@ -171,6 +191,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
171
191
|
buttons.push(
|
|
172
192
|
<button
|
|
173
193
|
key="float"
|
|
194
|
+
data-layout-path={path + "/button/float"}
|
|
174
195
|
title={floatTitle}
|
|
175
196
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON_FLOAT)}
|
|
176
197
|
onClick={onFloatTab}
|
|
@@ -188,6 +209,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
188
209
|
btns.push(
|
|
189
210
|
<button
|
|
190
211
|
key="max"
|
|
212
|
+
data-layout-path={path + "/button/max"}
|
|
191
213
|
title={node.isMaximized() ? minTitle : maxTitle}
|
|
192
214
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON_ + (node.isMaximized() ? "max" : "min"))}
|
|
193
215
|
onClick={onMaximizeToggle}
|
|
@@ -205,6 +227,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
205
227
|
btns.push(
|
|
206
228
|
<button
|
|
207
229
|
key="close"
|
|
230
|
+
data-layout-path={path + "/button/close"}
|
|
208
231
|
title={title}
|
|
209
232
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON_CLOSE)}
|
|
210
233
|
onClick={onClose}
|
|
@@ -269,7 +292,13 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
269
292
|
}
|
|
270
293
|
|
|
271
294
|
header = (
|
|
272
|
-
<div className={tabHeaderClasses} style={{ height: node.getHeaderHeight() + "px" }}
|
|
295
|
+
<div className={tabHeaderClasses} style={{ height: node.getHeaderHeight() + "px" }}
|
|
296
|
+
data-layout-path={path + "/header"}
|
|
297
|
+
onMouseDown={onMouseDown}
|
|
298
|
+
onContextMenu={onContextMenu}
|
|
299
|
+
onClick={onAuxMouseClick}
|
|
300
|
+
onAuxClick={onAuxMouseClick}
|
|
301
|
+
onTouchStart={onMouseDown}>
|
|
273
302
|
<div className={cm(CLASSES.FLEXLAYOUT__TABSET_HEADER_CONTENT)}>{headerContent}</div>
|
|
274
303
|
{headerToolbar}
|
|
275
304
|
</div>
|
|
@@ -284,7 +313,13 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
284
313
|
tabStripStyle["bottom"] = "0px";
|
|
285
314
|
}
|
|
286
315
|
tabStrip = (
|
|
287
|
-
<div className={tabStripClasses} style={tabStripStyle}
|
|
316
|
+
<div className={tabStripClasses} style={tabStripStyle}
|
|
317
|
+
data-layout-path={path + "/tabstrip"}
|
|
318
|
+
onMouseDown={onMouseDown}
|
|
319
|
+
onContextMenu={onContextMenu}
|
|
320
|
+
onClick={onAuxMouseClick}
|
|
321
|
+
onAuxClick={onAuxMouseClick}
|
|
322
|
+
onTouchStart={onMouseDown}>
|
|
288
323
|
<div ref={tabbarInnerRef} className={cm(CLASSES.FLEXLAYOUT__TABSET_TABBAR_INNER) + " " + cm(CLASSES.FLEXLAYOUT__TABSET_TABBAR_INNER_ + node.getTabLocation())}>
|
|
289
324
|
<div
|
|
290
325
|
style={{ left: position }}
|
|
@@ -300,9 +335,26 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
300
335
|
style = layout.styleFont(style);
|
|
301
336
|
|
|
302
337
|
return (
|
|
303
|
-
<div ref={selfRef}
|
|
338
|
+
<div ref={selfRef}
|
|
339
|
+
dir="ltr"
|
|
340
|
+
data-layout-path={path}
|
|
341
|
+
style={style}
|
|
342
|
+
className={cm(CLASSES.FLEXLAYOUT__TABSET)}
|
|
343
|
+
onWheel={onMouseWheel}>
|
|
304
344
|
{header}
|
|
305
345
|
{tabStrip}
|
|
306
346
|
</div>
|
|
307
347
|
);
|
|
308
348
|
};
|
|
349
|
+
|
|
350
|
+
/** @hidden @internal */
|
|
351
|
+
export function isAuxMouseEvent(event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) {
|
|
352
|
+
let auxEvent = false;
|
|
353
|
+
if (event.nativeEvent instanceof MouseEvent) {
|
|
354
|
+
if (event.nativeEvent.button !== 0 || event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) {
|
|
355
|
+
auxEvent = true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return auxEvent;
|
|
359
|
+
}
|
|
360
|
+
|