flexlayout-react 0.5.18 → 0.5.19
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 +8 -0
- package/README.md +109 -96
- package/declarations/Types.d.ts +7 -1
- package/declarations/view/Layout.d.ts +5 -0
- package/dist/flexlayout.js +12 -12
- package/dist/flexlayout_min.js +1 -1
- package/lib/PopupMenu.js +14 -9
- package/lib/PopupMenu.js.map +1 -1
- package/lib/Types.js +6 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/BorderNode.js +8 -7
- package/lib/model/BorderNode.js.map +1 -1
- package/lib/model/Model.js +7 -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 +14 -3
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTabSet.js +15 -4
- package/lib/view/BorderTabSet.js.map +1 -1
- package/lib/view/Layout.js +81 -48
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/TabButton.js +11 -2
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabFloating.js +23 -11
- package/lib/view/TabFloating.js.map +1 -1
- package/lib/view/TabSet.js +43 -18
- package/lib/view/TabSet.js.map +1 -1
- package/package.json +1 -1
- package/src/PopupMenu.tsx +28 -10
- package/src/Types.ts +6 -0
- package/src/model/BorderNode.ts +8 -7
- package/src/model/Model.ts +7 -3
- package/src/model/RowNode.ts +8 -5
- package/src/model/TabSetNode.ts +8 -4
- package/src/view/BorderButton.tsx +22 -3
- package/src/view/BorderTabSet.tsx +21 -4
- package/src/view/Layout.tsx +100 -58
- package/src/view/TabButton.tsx +16 -1
- package/src/view/TabFloating.tsx +36 -19
- package/src/view/TabSet.tsx +56 -17
- package/style/_base.scss +65 -41
- package/style/dark.css +81 -59
- package/style/dark.css.map +1 -1
- package/style/dark.scss +20 -20
- package/style/gray.css +81 -59
- package/style/gray.css.map +1 -1
- package/style/gray.scss +20 -20
- package/style/light.css +81 -59
- package/style/light.css.map +1 -1
- package/style/light.scss +18 -18
|
@@ -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 {
|
|
@@ -30,13 +31,24 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
30
31
|
|
|
31
32
|
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
|
|
32
33
|
|
|
34
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
35
|
+
if (isAuxMouseEvent(event)) {
|
|
36
|
+
layout.auxMouseClick(border, event);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
41
|
+
layout.showContextMenu(border, event);
|
|
42
|
+
};
|
|
43
|
+
|
|
33
44
|
const onInterceptMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.MouseEvent<HTMLButtonElement, MouseEvent> | React.TouchEvent<HTMLButtonElement>) => {
|
|
34
45
|
event.stopPropagation();
|
|
35
46
|
};
|
|
36
47
|
|
|
37
|
-
const onOverflowClick = () => {
|
|
48
|
+
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
38
49
|
const element = overflowbuttonRef.current!;
|
|
39
50
|
showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
|
|
51
|
+
event.stopPropagation();
|
|
40
52
|
};
|
|
41
53
|
|
|
42
54
|
const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
|
|
@@ -44,11 +56,12 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
44
56
|
userControlledLeft.current = false;
|
|
45
57
|
};
|
|
46
58
|
|
|
47
|
-
const onFloatTab = () => {
|
|
59
|
+
const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
48
60
|
const selectedTabNode = border.getChildren()[border.getSelected()] as TabNode;
|
|
49
61
|
if (selectedTabNode !== undefined) {
|
|
50
62
|
layout.doAction(Actions.floatTab(selectedTabNode.getId()));
|
|
51
63
|
}
|
|
64
|
+
event.stopPropagation();
|
|
52
65
|
};
|
|
53
66
|
|
|
54
67
|
const cm = layout.getClassName;
|
|
@@ -97,7 +110,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
97
110
|
<button
|
|
98
111
|
key="overflowbutton"
|
|
99
112
|
ref={overflowbuttonRef}
|
|
100
|
-
className={cm(
|
|
113
|
+
className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ + border.getLocation().getName())}
|
|
101
114
|
title={overflowTitle}
|
|
102
115
|
onClick={onOverflowClick}
|
|
103
116
|
onMouseDown={onInterceptMouseDown}
|
|
@@ -145,7 +158,11 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
145
158
|
}
|
|
146
159
|
|
|
147
160
|
return (
|
|
148
|
-
<div ref={selfRef} style={style} className={borderClasses}
|
|
161
|
+
<div ref={selfRef} dir="ltr" style={style} className={borderClasses}
|
|
162
|
+
onClick={onAuxMouseClick}
|
|
163
|
+
onAuxClick={onAuxMouseClick}
|
|
164
|
+
onContextMenu={onContextMenu}
|
|
165
|
+
onWheel={onMouseWheel}>
|
|
149
166
|
<div style={{ height: borderHeight }} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}>
|
|
150
167
|
<div style={innerStyle} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}>
|
|
151
168
|
{tabs}
|
package/src/view/Layout.tsx
CHANGED
|
@@ -28,6 +28,8 @@ import { IJsonTabNode } from "../model/IJsonModel";
|
|
|
28
28
|
|
|
29
29
|
export type CustomDragCallback = (dragging: TabNode | IJsonTabNode, over: TabNode, x: number, y: number, location: DockLocation) => void;
|
|
30
30
|
export type DragRectRenderCallback = (text: String, node?: Node, json?: IJsonTabNode) => React.ReactElement | undefined;
|
|
31
|
+
export type FloatingTabPlaceholderRenderCallback = (dockPopout: () => void, showPopout: () => void) => React.ReactElement | undefined;
|
|
32
|
+
export type NodeMouseEvent = (node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
31
33
|
|
|
32
34
|
export interface ILayoutProps {
|
|
33
35
|
model: Model;
|
|
@@ -41,11 +43,11 @@ export interface ILayoutProps {
|
|
|
41
43
|
onAction?: (action: Action) => Action | undefined;
|
|
42
44
|
onRenderTab?: (
|
|
43
45
|
node: TabNode,
|
|
44
|
-
renderValues: ITabRenderValues,
|
|
46
|
+
renderValues: ITabRenderValues, // change the values in this object as required
|
|
45
47
|
) => void;
|
|
46
48
|
onRenderTabSet?: (
|
|
47
49
|
tabSetNode: TabSetNode | BorderNode,
|
|
48
|
-
renderValues: ITabSetRenderValues,
|
|
50
|
+
renderValues: ITabSetRenderValues, // change the values in this object as required
|
|
49
51
|
) => void;
|
|
50
52
|
onModelChange?: (model: Model) => void;
|
|
51
53
|
onExternalDrag?: (event: React.DragEvent<HTMLDivElement>) => undefined | {
|
|
@@ -69,6 +71,9 @@ export interface ILayoutProps {
|
|
|
69
71
|
cursor?: string | undefined
|
|
70
72
|
};
|
|
71
73
|
onRenderDragRect?: DragRectRenderCallback;
|
|
74
|
+
onRenderFloatingTabPlaceholder?: FloatingTabPlaceholderRenderCallback;
|
|
75
|
+
onContextMenu?: NodeMouseEvent;
|
|
76
|
+
onAuxMouseClick?: NodeMouseEvent;
|
|
72
77
|
}
|
|
73
78
|
export interface IFontValues {
|
|
74
79
|
size?: string;
|
|
@@ -157,7 +162,9 @@ export interface ILayoutCallbacks {
|
|
|
157
162
|
styleFont: (style: Record<string, string>) => Record<string, string>;
|
|
158
163
|
setEditingTab(tabNode?: TabNode): void;
|
|
159
164
|
getEditingTab(): TabNode | undefined;
|
|
160
|
-
|
|
165
|
+
getOnRenderFloatingTabPlaceholder(): FloatingTabPlaceholderRenderCallback | undefined;
|
|
166
|
+
showContextMenu(node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) : void;
|
|
167
|
+
auxMouseClick(node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) : void;
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
// Popout windows work in latest browsers based on webkit (Chrome, Opera, Safari, latest Edge) and Firefox. They do
|
|
@@ -683,7 +690,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
683
690
|
|
|
684
691
|
this.dragDivText = dragText;
|
|
685
692
|
this.dragDiv = this.currentDocument!.createElement("div");
|
|
686
|
-
this.dragDiv.className = this.getClassName(
|
|
693
|
+
this.dragDiv.className = this.getClassName(CLASSES.FLEXLAYOUT__DRAG_RECT);
|
|
687
694
|
this.dragDiv.addEventListener("mousedown", this.onDragDivMouseDown);
|
|
688
695
|
this.dragDiv.addEventListener("touchstart", this.onDragDivMouseDown);
|
|
689
696
|
|
|
@@ -867,62 +874,13 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
867
874
|
|
|
868
875
|
let dropInfo = this.props.model._findDropTargetNode(this.dragNode!, pos.x, pos.y);
|
|
869
876
|
if (dropInfo) {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
this.customDrop = undefined;
|
|
873
|
-
|
|
874
|
-
const dragging = this.newTabJson || (this.dragNode instanceof TabNode ? this.dragNode : undefined);
|
|
875
|
-
if (dragging && (dropInfo.node instanceof TabSetNode || dropInfo.node instanceof BorderNode) && dropInfo.index === -1) {
|
|
876
|
-
const selected = dropInfo.node.getSelectedNode() as TabNode | undefined;
|
|
877
|
-
const tabRect = selected?.getRect()
|
|
878
|
-
|
|
879
|
-
if (selected && tabRect?.contains(pos.x, pos.y)) {
|
|
880
|
-
let customDrop: ICustomDropDestination | undefined = undefined;
|
|
881
|
-
|
|
882
|
-
try {
|
|
883
|
-
const dest = this.onTabDrag(dragging, selected, pos.x - tabRect.x, pos.y - tabRect.y, dropInfo.location, () => this.onDragMove(event));
|
|
884
|
-
|
|
885
|
-
if (dest) {
|
|
886
|
-
customDrop = {
|
|
887
|
-
rect: new Rect(dest.x + tabRect.x, dest.y + tabRect.y, dest.width, dest.height),
|
|
888
|
-
callback: dest.callback,
|
|
889
|
-
invalidated: dest.invalidated,
|
|
890
|
-
dragging: dragging,
|
|
891
|
-
over: selected,
|
|
892
|
-
x: pos.x - tabRect.x,
|
|
893
|
-
y: pos.y - tabRect.y,
|
|
894
|
-
location: dropInfo.location,
|
|
895
|
-
cursor: dest.cursor
|
|
896
|
-
};
|
|
897
|
-
}
|
|
898
|
-
} catch (e) {
|
|
899
|
-
console.error(e)
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
if (customDrop?.callback === currentCallback) {
|
|
903
|
-
invalidated = undefined;
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
this.customDrop = customDrop;
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
this.dropInfo = dropInfo;
|
|
911
|
-
this.outlineDiv!.className = this.getClassName(this.customDrop ? "flexlayout__outline_rect" : dropInfo.className);
|
|
912
|
-
|
|
913
|
-
if (this.customDrop) {
|
|
914
|
-
this.customDrop.rect.positionElement(this.outlineDiv!);
|
|
877
|
+
if (this.props.onTabDrag) {
|
|
878
|
+
this.handleCustomTabDrag(dropInfo, pos, event);
|
|
915
879
|
} else {
|
|
880
|
+
this.dropInfo = dropInfo;
|
|
881
|
+
this.outlineDiv!.className = this.getClassName(dropInfo.className);
|
|
916
882
|
dropInfo.rect.positionElement(this.outlineDiv!);
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
DragDrop.instance.setGlassCursorOverride(this.customDrop?.cursor);
|
|
920
|
-
this.outlineDiv!.style.visibility = "visible";
|
|
921
|
-
|
|
922
|
-
try {
|
|
923
|
-
invalidated?.();
|
|
924
|
-
} catch (e) {
|
|
925
|
-
console.error(e);
|
|
883
|
+
this.outlineDiv!.style.visibility = "visible";
|
|
926
884
|
}
|
|
927
885
|
}
|
|
928
886
|
};
|
|
@@ -943,6 +901,10 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
943
901
|
try {
|
|
944
902
|
const { callback, dragging, over, x, y, location } = this.customDrop;
|
|
945
903
|
callback(dragging, over, x, y, location);
|
|
904
|
+
if (this.fnNewNodeDropped != null) {
|
|
905
|
+
this.fnNewNodeDropped();
|
|
906
|
+
this.fnNewNodeDropped = undefined;
|
|
907
|
+
}
|
|
946
908
|
} catch (e) {
|
|
947
909
|
console.error(e)
|
|
948
910
|
}
|
|
@@ -961,6 +923,67 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
961
923
|
this.setState({ showHiddenBorder: DockLocation.CENTER });
|
|
962
924
|
};
|
|
963
925
|
|
|
926
|
+
/** @hidden @internal */
|
|
927
|
+
private handleCustomTabDrag(dropInfo: DropInfo, pos: { x: number; y: number; }, event: React.MouseEvent<Element, MouseEvent>) {
|
|
928
|
+
let invalidated = this.customDrop?.invalidated;
|
|
929
|
+
const currentCallback = this.customDrop?.callback;
|
|
930
|
+
this.customDrop = undefined;
|
|
931
|
+
|
|
932
|
+
const dragging = this.newTabJson || (this.dragNode instanceof TabNode ? this.dragNode : undefined);
|
|
933
|
+
if (dragging && (dropInfo.node instanceof TabSetNode || dropInfo.node instanceof BorderNode) && dropInfo.index === -1) {
|
|
934
|
+
const selected = dropInfo.node.getSelectedNode() as TabNode | undefined;
|
|
935
|
+
const tabRect = selected?.getRect();
|
|
936
|
+
|
|
937
|
+
if (selected && tabRect?.contains(pos.x, pos.y)) {
|
|
938
|
+
let customDrop: ICustomDropDestination | undefined = undefined;
|
|
939
|
+
|
|
940
|
+
try {
|
|
941
|
+
const dest = this.onTabDrag(dragging, selected, pos.x - tabRect.x, pos.y - tabRect.y, dropInfo.location, () => this.onDragMove(event));
|
|
942
|
+
|
|
943
|
+
if (dest) {
|
|
944
|
+
customDrop = {
|
|
945
|
+
rect: new Rect(dest.x + tabRect.x, dest.y + tabRect.y, dest.width, dest.height),
|
|
946
|
+
callback: dest.callback,
|
|
947
|
+
invalidated: dest.invalidated,
|
|
948
|
+
dragging: dragging,
|
|
949
|
+
over: selected,
|
|
950
|
+
x: pos.x - tabRect.x,
|
|
951
|
+
y: pos.y - tabRect.y,
|
|
952
|
+
location: dropInfo.location,
|
|
953
|
+
cursor: dest.cursor
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
} catch (e) {
|
|
957
|
+
console.error(e);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
if (customDrop?.callback === currentCallback) {
|
|
961
|
+
invalidated = undefined;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
this.customDrop = customDrop;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
this.dropInfo = dropInfo;
|
|
969
|
+
this.outlineDiv!.className = this.getClassName(this.customDrop ? CLASSES.FLEXLAYOUT__OUTLINE_RECT : dropInfo.className);
|
|
970
|
+
|
|
971
|
+
if (this.customDrop) {
|
|
972
|
+
this.customDrop.rect.positionElement(this.outlineDiv!);
|
|
973
|
+
} else {
|
|
974
|
+
dropInfo.rect.positionElement(this.outlineDiv!);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
DragDrop.instance.setGlassCursorOverride(this.customDrop?.cursor);
|
|
978
|
+
this.outlineDiv!.style.visibility = "visible";
|
|
979
|
+
|
|
980
|
+
try {
|
|
981
|
+
invalidated?.();
|
|
982
|
+
} catch (e) {
|
|
983
|
+
console.error(e);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
964
987
|
/** @hidden @internal */
|
|
965
988
|
onDragEnter(event: React.DragEvent<HTMLDivElement>) {
|
|
966
989
|
// DragDrop keeps track of number of dragenters minus the number of
|
|
@@ -1125,6 +1148,25 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
1125
1148
|
}
|
|
1126
1149
|
return message;
|
|
1127
1150
|
}
|
|
1151
|
+
|
|
1152
|
+
/** @hidden @internal */
|
|
1153
|
+
getOnRenderFloatingTabPlaceholder() {
|
|
1154
|
+
return this.props.onRenderFloatingTabPlaceholder;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/** @hidden @internal */
|
|
1158
|
+
showContextMenu(node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) {
|
|
1159
|
+
if (this.props.onContextMenu) {
|
|
1160
|
+
this.props.onContextMenu(node, event);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/** @hidden @internal */
|
|
1165
|
+
auxMouseClick(node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) {
|
|
1166
|
+
if (this.props.onAuxMouseClick) {
|
|
1167
|
+
this.props.onAuxMouseClick(node, event);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1128
1170
|
}
|
|
1129
1171
|
|
|
1130
1172
|
// wrapper round the drag rect renderer that can call
|
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 {
|
|
@@ -28,12 +29,23 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
28
29
|
const contentWidth = React.useRef<number>(0);
|
|
29
30
|
|
|
30
31
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
31
|
-
|
|
32
|
+
|
|
33
|
+
if (!isAuxMouseEvent(event) && !layout.getEditingTab()) {
|
|
32
34
|
const message = layout.i18nName(I18nLabel.Move_Tab, node.getName());
|
|
33
35
|
layout.dragStart(event, message, node, node.isEnableDrag(), onClick, onDoubleClick);
|
|
34
36
|
}
|
|
35
37
|
};
|
|
36
38
|
|
|
39
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
40
|
+
if (isAuxMouseEvent(event)) {
|
|
41
|
+
layout.auxMouseClick(node, event);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
46
|
+
layout.showContextMenu(node, event);
|
|
47
|
+
};
|
|
48
|
+
|
|
37
49
|
const onClick = () => {
|
|
38
50
|
layout.doAction(Actions.selectTab(node.getId()));
|
|
39
51
|
};
|
|
@@ -211,6 +223,9 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
211
223
|
}}
|
|
212
224
|
className={classNames}
|
|
213
225
|
onMouseDown={onMouseDown}
|
|
226
|
+
onClick={onAuxMouseClick}
|
|
227
|
+
onAuxClick={onAuxMouseClick}
|
|
228
|
+
onContextMenu={onContextMenu}
|
|
214
229
|
onTouchStart={onMouseDown}
|
|
215
230
|
title={node.getHelpText()}
|
|
216
231
|
>
|
package/src/view/TabFloating.tsx
CHANGED
|
@@ -17,6 +17,16 @@ export interface ITabFloatingProps {
|
|
|
17
17
|
export const TabFloating = (props: ITabFloatingProps) => {
|
|
18
18
|
const { layout, selected, node } = props;
|
|
19
19
|
|
|
20
|
+
const showPopout = () => {
|
|
21
|
+
if (node.getWindow()) {
|
|
22
|
+
node.getWindow()!.focus();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const dockPopout = () => {
|
|
27
|
+
layout.doAction(Actions.unFloatTab(node.getId()));
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
const onMouseDown = () => {
|
|
21
31
|
const parent = node.getParent() as TabSetNode;
|
|
22
32
|
if (parent.getType() === TabSetNode.TYPE) {
|
|
@@ -28,14 +38,12 @@ export const TabFloating = (props: ITabFloatingProps) => {
|
|
|
28
38
|
|
|
29
39
|
const onClickFocus = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
|
30
40
|
event.preventDefault();
|
|
31
|
-
|
|
32
|
-
node.getWindow()!.focus();
|
|
33
|
-
}
|
|
41
|
+
showPopout();
|
|
34
42
|
};
|
|
35
43
|
|
|
36
44
|
const onClickDock = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
|
37
45
|
event.preventDefault();
|
|
38
|
-
|
|
46
|
+
dockPopout();
|
|
39
47
|
};
|
|
40
48
|
|
|
41
49
|
const cm = layout.getClassName;
|
|
@@ -48,21 +56,30 @@ export const TabFloating = (props: ITabFloatingProps) => {
|
|
|
48
56
|
const showMessage = layout.i18nName(I18nLabel.Floating_Window_Show_Window);
|
|
49
57
|
const dockMessage = layout.i18nName(I18nLabel.Floating_Window_Dock_Window);
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
const customRenderCallback = layout.getOnRenderFloatingTabPlaceholder();
|
|
60
|
+
if (customRenderCallback) {
|
|
61
|
+
return (
|
|
62
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)} onMouseDown={onMouseDown} onTouchStart={onMouseDown} style={style}>
|
|
63
|
+
{customRenderCallback(dockPopout, showPopout)}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
} else {
|
|
67
|
+
return (
|
|
68
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)} onMouseDown={onMouseDown} onTouchStart={onMouseDown} style={style}>
|
|
69
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING_INNER)}>
|
|
70
|
+
<div>{message}</div>
|
|
71
|
+
<div>
|
|
72
|
+
<a href="#" onClick={onClickFocus}>
|
|
73
|
+
{showMessage}
|
|
74
|
+
</a>
|
|
75
|
+
</div>
|
|
76
|
+
<div>
|
|
77
|
+
<a href="#" onClick={onClickDock}>
|
|
78
|
+
{dockMessage}
|
|
79
|
+
</a>
|
|
80
|
+
</div>
|
|
64
81
|
</div>
|
|
65
82
|
</div>
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
);
|
|
84
|
+
}
|
|
68
85
|
};
|
package/src/view/TabSet.tsx
CHANGED
|
@@ -17,7 +17,7 @@ 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
21
|
}
|
|
22
22
|
|
|
23
23
|
/** @hidden @internal */
|
|
@@ -31,9 +31,10 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
31
31
|
|
|
32
32
|
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated } = useTabOverflow(node, Orientation.HORZ, toolbarRef, stickyButtonsRef);
|
|
33
33
|
|
|
34
|
-
const onOverflowClick = () => {
|
|
34
|
+
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
35
35
|
const element = overflowbuttonRef.current!;
|
|
36
36
|
showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
|
|
37
|
+
event.stopPropagation();
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
|
|
@@ -42,37 +43,53 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
name =
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
|
|
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) => {
|
|
@@ -269,7 +286,12 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
269
286
|
}
|
|
270
287
|
|
|
271
288
|
header = (
|
|
272
|
-
<div className={tabHeaderClasses} style={{ height: node.getHeaderHeight() + "px" }}
|
|
289
|
+
<div className={tabHeaderClasses} style={{ height: node.getHeaderHeight() + "px" }}
|
|
290
|
+
onMouseDown={onMouseDown}
|
|
291
|
+
onContextMenu={onContextMenu}
|
|
292
|
+
onClick={onAuxMouseClick}
|
|
293
|
+
onAuxClick={onAuxMouseClick}
|
|
294
|
+
onTouchStart={onMouseDown}>
|
|
273
295
|
<div className={cm(CLASSES.FLEXLAYOUT__TABSET_HEADER_CONTENT)}>{headerContent}</div>
|
|
274
296
|
{headerToolbar}
|
|
275
297
|
</div>
|
|
@@ -284,7 +306,12 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
284
306
|
tabStripStyle["bottom"] = "0px";
|
|
285
307
|
}
|
|
286
308
|
tabStrip = (
|
|
287
|
-
<div className={tabStripClasses} style={tabStripStyle}
|
|
309
|
+
<div className={tabStripClasses} style={tabStripStyle}
|
|
310
|
+
onMouseDown={onMouseDown}
|
|
311
|
+
onContextMenu={onContextMenu}
|
|
312
|
+
onClick={onAuxMouseClick}
|
|
313
|
+
onAuxClick={onAuxMouseClick}
|
|
314
|
+
onTouchStart={onMouseDown}>
|
|
288
315
|
<div ref={tabbarInnerRef} className={cm(CLASSES.FLEXLAYOUT__TABSET_TABBAR_INNER) + " " + cm(CLASSES.FLEXLAYOUT__TABSET_TABBAR_INNER_ + node.getTabLocation())}>
|
|
289
316
|
<div
|
|
290
317
|
style={{ left: position }}
|
|
@@ -300,9 +327,21 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
300
327
|
style = layout.styleFont(style);
|
|
301
328
|
|
|
302
329
|
return (
|
|
303
|
-
<div ref={selfRef} style={style} className={cm(CLASSES.FLEXLAYOUT__TABSET)} onWheel={onMouseWheel}>
|
|
330
|
+
<div ref={selfRef} dir="ltr" style={style} className={cm(CLASSES.FLEXLAYOUT__TABSET)} onWheel={onMouseWheel}>
|
|
304
331
|
{header}
|
|
305
332
|
{tabStrip}
|
|
306
333
|
</div>
|
|
307
334
|
);
|
|
308
335
|
};
|
|
336
|
+
|
|
337
|
+
/** @hidden @internal */
|
|
338
|
+
export function isAuxMouseEvent(event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) {
|
|
339
|
+
let auxEvent = false;
|
|
340
|
+
if (event.nativeEvent instanceof MouseEvent) {
|
|
341
|
+
if (event.nativeEvent.button !== 0 || event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) {
|
|
342
|
+
auxEvent = true;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return auxEvent;
|
|
346
|
+
}
|
|
347
|
+
|