flexlayout-react 0.7.15 → 0.8.0

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.
Files changed (252) hide show
  1. package/ChangeLog.txt +23 -0
  2. package/README.md +157 -330
  3. package/Screenshot_light.png +0 -0
  4. package/Screenshot_rounded.png +0 -0
  5. package/declarations/Attribute.d.ts +1 -1
  6. package/declarations/AttributeDefinitions.d.ts +1 -1
  7. package/declarations/DockLocation.d.ts +12 -12
  8. package/declarations/DropInfo.d.ts +12 -12
  9. package/declarations/I18nLabel.d.ts +12 -14
  10. package/declarations/Orientation.d.ts +7 -7
  11. package/declarations/PopupMenu.d.ts +1 -1
  12. package/declarations/Rect.d.ts +41 -28
  13. package/declarations/Types.d.ts +95 -79
  14. package/declarations/examples/demo/Utils.d.ts +4 -0
  15. package/declarations/index.d.ts +21 -22
  16. package/declarations/model/Action.d.ts +5 -5
  17. package/declarations/model/Actions.d.ts +127 -110
  18. package/declarations/model/BorderNode.d.ts +30 -34
  19. package/declarations/model/BorderSet.d.ts +3 -4
  20. package/declarations/model/ICloseType.d.ts +5 -5
  21. package/declarations/model/IDraggable.d.ts +2 -2
  22. package/declarations/model/IDropTarget.d.ts +2 -2
  23. package/declarations/model/IJsonModel.d.ts +811 -149
  24. package/declarations/model/LayoutWindow.d.ts +28 -0
  25. package/declarations/model/Model.d.ts +91 -86
  26. package/declarations/model/Node.d.ts +17 -17
  27. package/declarations/model/RowNode.d.ts +10 -11
  28. package/declarations/model/TabNode.d.ts +44 -37
  29. package/declarations/model/TabSetNode.d.ts +44 -41
  30. package/declarations/model/Utils.d.ts +1 -1
  31. package/declarations/model/WindowLayout.d.ts +24 -0
  32. package/declarations/src/Attribute.d.ts +1 -0
  33. package/declarations/src/AttributeDefinitions.d.ts +1 -0
  34. package/declarations/src/DockLocation.d.ts +12 -0
  35. package/declarations/src/DropInfo.d.ts +12 -0
  36. package/declarations/src/I18nLabel.d.ts +10 -0
  37. package/declarations/src/Orientation.d.ts +7 -0
  38. package/declarations/src/PopupMenu.d.ts +1 -0
  39. package/declarations/src/Rect.d.ts +31 -0
  40. package/declarations/src/Types.d.ts +92 -0
  41. package/declarations/src/index.d.ts +20 -0
  42. package/declarations/src/model/Action.d.ts +5 -0
  43. package/declarations/src/model/Actions.d.ts +110 -0
  44. package/declarations/src/model/BorderNode.d.ts +28 -0
  45. package/declarations/src/model/BorderSet.d.ts +3 -0
  46. package/declarations/src/model/ICloseType.d.ts +5 -0
  47. package/declarations/src/model/IDraggable.d.ts +2 -0
  48. package/declarations/src/model/IDropTarget.d.ts +2 -0
  49. package/declarations/src/model/IJsonModel.d.ts +153 -0
  50. package/declarations/src/model/Model.d.ts +98 -0
  51. package/declarations/src/model/Node.d.ts +16 -0
  52. package/declarations/src/model/RowNode.d.ts +11 -0
  53. package/declarations/src/model/TabNode.d.ts +36 -0
  54. package/declarations/src/model/TabSetNode.d.ts +37 -0
  55. package/declarations/src/model/Utils.d.ts +1 -0
  56. package/declarations/src/view/BorderButton.d.ts +1 -0
  57. package/declarations/src/view/BorderTab.d.ts +2 -0
  58. package/declarations/src/view/BorderTabSet.d.ts +1 -0
  59. package/declarations/src/view/DragContainer.d.ts +1 -0
  60. package/declarations/src/view/ErrorBoundary.d.ts +1 -0
  61. package/declarations/src/view/FloatingWindow.d.ts +1 -0
  62. package/declarations/src/view/Icons.d.ts +7 -0
  63. package/declarations/src/view/Layout.d.ts +113 -0
  64. package/declarations/src/view/Overlay.d.ts +1 -0
  65. package/declarations/src/view/PopupMenu.d.ts +1 -0
  66. package/declarations/src/view/Row.d.ts +1 -0
  67. package/declarations/src/view/Splitter.d.ts +1 -0
  68. package/declarations/src/view/Tab.d.ts +1 -0
  69. package/declarations/src/view/TabButton.d.ts +1 -0
  70. package/declarations/src/view/TabButtonStamp.d.ts +1 -0
  71. package/declarations/src/view/TabOverflowHook.d.ts +1 -0
  72. package/declarations/src/view/TabSet.d.ts +1 -0
  73. package/declarations/src/view/Utils.d.ts +4 -0
  74. package/declarations/view/BorderButton.d.ts +1 -1
  75. package/declarations/view/BorderTab.d.ts +2 -0
  76. package/declarations/view/BorderTabSet.d.ts +1 -1
  77. package/declarations/view/DragContainer.d.ts +1 -0
  78. package/declarations/view/ErrorBoundary.d.ts +1 -1
  79. package/declarations/view/ExtendedResizeObserver.d.ts +23 -0
  80. package/declarations/view/FloatingWindow.d.ts +1 -1
  81. package/declarations/view/Icons.d.ts +8 -7
  82. package/declarations/view/Layout.d.ts +139 -161
  83. package/declarations/view/Overlay.d.ts +1 -0
  84. package/declarations/view/PopoutWindow.d.ts +1 -0
  85. package/declarations/view/PopupMenu.d.ts +1 -0
  86. package/declarations/view/Row.d.ts +1 -0
  87. package/declarations/view/SizeTracker.d.ts +10 -0
  88. package/declarations/view/Splitter.d.ts +1 -1
  89. package/declarations/view/Tab.d.ts +1 -1
  90. package/declarations/view/TabButton.d.ts +1 -1
  91. package/declarations/view/TabButtonStamp.d.ts +1 -1
  92. package/declarations/view/TabOverflowHook.d.ts +1 -1
  93. package/declarations/view/TabSet.d.ts +1 -1
  94. package/declarations/view/Utils.d.ts +11 -1
  95. package/dist/bundles/demo.js +232052 -0
  96. package/dist/bundles/demo.js.map +1 -0
  97. package/dist/flexlayout.js +122 -92
  98. package/dist/flexlayout_min.js +1 -1
  99. package/lib/Attribute.js +42 -31
  100. package/lib/Attribute.js.map +1 -1
  101. package/lib/AttributeDefinitions.js +131 -108
  102. package/lib/AttributeDefinitions.js.map +1 -1
  103. package/lib/DockLocation.js +120 -124
  104. package/lib/DockLocation.js.map +1 -1
  105. package/lib/DropInfo.js +9 -13
  106. package/lib/DropInfo.js.map +1 -1
  107. package/lib/I18nLabel.js +13 -18
  108. package/lib/I18nLabel.js.map +1 -1
  109. package/lib/Orientation.js +22 -26
  110. package/lib/Orientation.js.map +1 -1
  111. package/lib/Rect.js +104 -72
  112. package/lib/Rect.js.map +1 -1
  113. package/lib/Types.js +96 -83
  114. package/lib/Types.js.map +1 -1
  115. package/lib/index.js +21 -38
  116. package/lib/index.js.map +1 -1
  117. package/lib/model/Action.js +6 -10
  118. package/lib/model/Action.js.map +1 -1
  119. package/lib/model/Actions.js +169 -155
  120. package/lib/model/Actions.js.map +1 -1
  121. package/lib/model/BorderNode.js +385 -406
  122. package/lib/model/BorderNode.js.map +1 -1
  123. package/lib/model/BorderSet.js +66 -121
  124. package/lib/model/BorderSet.js.map +1 -1
  125. package/lib/model/ICloseType.js +6 -9
  126. package/lib/model/ICloseType.js.map +1 -1
  127. package/lib/model/IDraggable.js +1 -2
  128. package/lib/model/IDropTarget.js +1 -2
  129. package/lib/model/IJsonModel.js +1 -2
  130. package/lib/model/LayoutWindow.js +83 -0
  131. package/lib/model/LayoutWindow.js.map +1 -0
  132. package/lib/model/Model.js +614 -496
  133. package/lib/model/Model.js.map +1 -1
  134. package/lib/model/Node.js +217 -228
  135. package/lib/model/Node.js.map +1 -1
  136. package/lib/model/RowNode.js +491 -504
  137. package/lib/model/RowNode.js.map +1 -1
  138. package/lib/model/TabNode.js +289 -184
  139. package/lib/model/TabNode.js.map +1 -1
  140. package/lib/model/TabSetNode.js +457 -446
  141. package/lib/model/TabSetNode.js.map +1 -1
  142. package/lib/model/Utils.js +47 -82
  143. package/lib/model/Utils.js.map +1 -1
  144. package/lib/view/BorderButton.js +124 -138
  145. package/lib/view/BorderButton.js.map +1 -1
  146. package/lib/view/BorderTab.js +47 -0
  147. package/lib/view/BorderTab.js.map +1 -0
  148. package/lib/view/BorderTabSet.js +134 -128
  149. package/lib/view/BorderTabSet.js.map +1 -1
  150. package/lib/view/DragContainer.js +16 -0
  151. package/lib/view/DragContainer.js.map +1 -0
  152. package/lib/view/ErrorBoundary.js +23 -27
  153. package/lib/view/ErrorBoundary.js.map +1 -1
  154. package/lib/view/Icons.js +40 -45
  155. package/lib/view/Icons.js.map +1 -1
  156. package/lib/view/Layout.js +918 -907
  157. package/lib/view/Layout.js.map +1 -1
  158. package/lib/view/Overlay.js +9 -0
  159. package/lib/view/Overlay.js.map +1 -0
  160. package/lib/view/PopoutWindow.js +129 -0
  161. package/lib/view/PopoutWindow.js.map +1 -0
  162. package/lib/view/PopupMenu.js +71 -0
  163. package/lib/view/PopupMenu.js.map +1 -0
  164. package/lib/view/Row.js +45 -0
  165. package/lib/view/Row.js.map +1 -0
  166. package/lib/view/SizeTracker.js +11 -0
  167. package/lib/view/SizeTracker.js.map +1 -0
  168. package/lib/view/Splitter.js +191 -147
  169. package/lib/view/Splitter.js.map +1 -1
  170. package/lib/view/Tab.js +86 -60
  171. package/lib/view/Tab.js.map +1 -1
  172. package/lib/view/TabButton.js +122 -135
  173. package/lib/view/TabButton.js.map +1 -1
  174. package/lib/view/TabButtonStamp.js +16 -21
  175. package/lib/view/TabButtonStamp.js.map +1 -1
  176. package/lib/view/TabOverflowHook.js +150 -149
  177. package/lib/view/TabOverflowHook.js.map +1 -1
  178. package/lib/view/TabSet.js +267 -234
  179. package/lib/view/TabSet.js.map +1 -1
  180. package/lib/view/Utils.js +126 -68
  181. package/lib/view/Utils.js.map +1 -1
  182. package/package.json +36 -30
  183. package/src/Attribute.ts +23 -0
  184. package/src/AttributeDefinitions.ts +38 -15
  185. package/src/DockLocation.ts +13 -13
  186. package/src/I18nLabel.ts +7 -9
  187. package/src/Rect.ts +53 -1
  188. package/src/Types.ts +16 -0
  189. package/src/index.ts +1 -2
  190. package/src/model/Actions.ts +49 -29
  191. package/src/model/BorderNode.ts +208 -214
  192. package/src/model/BorderSet.ts +42 -91
  193. package/src/model/IJsonModel.ts +883 -103
  194. package/src/model/LayoutWindow.ts +121 -0
  195. package/src/model/Model.ts +488 -366
  196. package/src/model/Node.ts +98 -111
  197. package/src/model/RowNode.ts +323 -319
  198. package/src/model/TabNode.ts +294 -110
  199. package/src/model/TabSetNode.ts +300 -242
  200. package/src/model/Utils.ts +6 -32
  201. package/src/view/BorderButton.tsx +32 -52
  202. package/src/view/BorderTab.tsx +70 -0
  203. package/src/view/BorderTabSet.tsx +64 -52
  204. package/src/view/DragContainer.tsx +32 -0
  205. package/src/view/Icons.tsx +6 -0
  206. package/src/view/Layout.tsx +1051 -1046
  207. package/src/view/Overlay.tsx +22 -0
  208. package/src/view/PopoutWindow.tsx +152 -0
  209. package/src/{PopupMenu.tsx → view/PopupMenu.tsx} +36 -31
  210. package/src/view/Row.tsx +68 -0
  211. package/src/view/SizeTracker.tsx +20 -0
  212. package/src/view/Splitter.tsx +167 -112
  213. package/src/view/Tab.tsx +76 -42
  214. package/src/view/TabButton.tsx +36 -55
  215. package/src/view/TabButtonStamp.tsx +5 -9
  216. package/src/view/TabOverflowHook.tsx +14 -9
  217. package/src/view/TabSet.tsx +217 -176
  218. package/src/view/Utils.tsx +119 -39
  219. package/style/_base.scss +140 -34
  220. package/style/dark.css +685 -580
  221. package/style/dark.css.map +1 -1
  222. package/style/dark.scss +3 -1
  223. package/style/gray.css +668 -563
  224. package/style/gray.css.map +1 -1
  225. package/style/gray.scss +2 -0
  226. package/style/light.css +669 -564
  227. package/style/light.css.map +1 -1
  228. package/style/light.scss +4 -2
  229. package/style/rounded.css +697 -0
  230. package/style/rounded.css.map +1 -0
  231. package/style/rounded.scss +194 -0
  232. package/style/underline.css +690 -585
  233. package/style/underline.css.map +1 -1
  234. package/style/underline.scss +2 -0
  235. package/cypress.config.ts +0 -16
  236. package/lib/DragDrop.js +0 -316
  237. package/lib/DragDrop.js.map +0 -1
  238. package/lib/PopupMenu.js +0 -68
  239. package/lib/PopupMenu.js.map +0 -1
  240. package/lib/model/SplitterNode.js +0 -72
  241. package/lib/model/SplitterNode.js.map +0 -1
  242. package/lib/view/FloatingWindow.js +0 -123
  243. package/lib/view/FloatingWindow.js.map +0 -1
  244. package/lib/view/FloatingWindowTab.js +0 -19
  245. package/lib/view/FloatingWindowTab.js.map +0 -1
  246. package/lib/view/TabFloating.js +0 -66
  247. package/lib/view/TabFloating.js.map +0 -1
  248. package/src/DragDrop.ts +0 -392
  249. package/src/model/SplitterNode.ts +0 -78
  250. package/src/view/FloatingWindow.tsx +0 -140
  251. package/src/view/FloatingWindowTab.tsx +0 -29
  252. package/src/view/TabFloating.tsx +0 -101
@@ -1,497 +1,615 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Model = void 0;
4
- const Attribute_1 = require("../Attribute");
5
- const AttributeDefinitions_1 = require("../AttributeDefinitions");
6
- const DockLocation_1 = require("../DockLocation");
7
- const Orientation_1 = require("../Orientation");
8
- const Rect_1 = require("../Rect");
9
- const Actions_1 = require("./Actions");
10
- const BorderNode_1 = require("./BorderNode");
11
- const BorderSet_1 = require("./BorderSet");
12
- const RowNode_1 = require("./RowNode");
13
- const TabNode_1 = require("./TabNode");
14
- const TabSetNode_1 = require("./TabSetNode");
15
- const Utils_1 = require("./Utils");
16
- /**
17
- * Class containing the Tree of Nodes used by the FlexLayout component
18
- */
19
- class Model {
20
- /**
21
- * Loads the model from the given json object
22
- * @param json the json model to load
23
- * @returns {Model} a new Model object
24
- */
25
- static fromJson(json) {
26
- const model = new Model();
27
- Model._attributeDefinitions.fromJson(json.global, model._attributes);
28
- if (json.borders) {
29
- model._borders = BorderSet_1.BorderSet._fromJson(json.borders, model);
30
- }
31
- model._root = RowNode_1.RowNode._fromJson(json.layout, model);
32
- model._tidy(); // initial tidy of node tree
33
- return model;
34
- }
35
- /** @internal */
36
- static _createAttributeDefinitions() {
37
- const attributeDefinitions = new AttributeDefinitions_1.AttributeDefinitions();
38
- attributeDefinitions.add("legacyOverflowMenu", false).setType(Attribute_1.Attribute.BOOLEAN);
39
- attributeDefinitions.add("enableEdgeDock", true).setType(Attribute_1.Attribute.BOOLEAN);
40
- attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute_1.Attribute.BOOLEAN);
41
- attributeDefinitions.add("marginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
42
- .setType("IInsets");
43
- attributeDefinitions.add("enableUseVisibility", false).setType(Attribute_1.Attribute.BOOLEAN);
44
- attributeDefinitions.add("enableRotateBorderIcons", true).setType(Attribute_1.Attribute.BOOLEAN);
45
- // splitter
46
- attributeDefinitions.add("splitterSize", -1).setType(Attribute_1.Attribute.NUMBER);
47
- attributeDefinitions.add("splitterExtra", 0).setType(Attribute_1.Attribute.NUMBER);
48
- // tab
49
- attributeDefinitions.add("tabEnableClose", true).setType(Attribute_1.Attribute.BOOLEAN);
50
- attributeDefinitions.add("tabCloseType", 1).setType("ICloseType");
51
- attributeDefinitions.add("tabEnableFloat", false).setType(Attribute_1.Attribute.BOOLEAN);
52
- attributeDefinitions.add("tabEnableDrag", true).setType(Attribute_1.Attribute.BOOLEAN);
53
- attributeDefinitions.add("tabEnableRename", true).setType(Attribute_1.Attribute.BOOLEAN);
54
- attributeDefinitions.add("tabContentClassName", undefined).setType(Attribute_1.Attribute.STRING);
55
- attributeDefinitions.add("tabClassName", undefined).setType(Attribute_1.Attribute.STRING);
56
- attributeDefinitions.add("tabIcon", undefined).setType(Attribute_1.Attribute.STRING);
57
- attributeDefinitions.add("tabEnableRenderOnDemand", true).setType(Attribute_1.Attribute.BOOLEAN);
58
- attributeDefinitions.add("tabDragSpeed", 0.3).setType(Attribute_1.Attribute.NUMBER);
59
- attributeDefinitions.add("tabBorderWidth", -1).setType(Attribute_1.Attribute.NUMBER);
60
- attributeDefinitions.add("tabBorderHeight", -1).setType(Attribute_1.Attribute.NUMBER);
61
- // tabset
62
- attributeDefinitions.add("tabSetEnableDeleteWhenEmpty", true).setType(Attribute_1.Attribute.BOOLEAN);
63
- attributeDefinitions.add("tabSetEnableDrop", true).setType(Attribute_1.Attribute.BOOLEAN);
64
- attributeDefinitions.add("tabSetEnableDrag", true).setType(Attribute_1.Attribute.BOOLEAN);
65
- attributeDefinitions.add("tabSetEnableDivide", true).setType(Attribute_1.Attribute.BOOLEAN);
66
- attributeDefinitions.add("tabSetEnableMaximize", true).setType(Attribute_1.Attribute.BOOLEAN);
67
- attributeDefinitions.add("tabSetEnableClose", false).setType(Attribute_1.Attribute.BOOLEAN);
68
- attributeDefinitions.add("tabSetEnableSingleTabStretch", false).setType(Attribute_1.Attribute.BOOLEAN);
69
- attributeDefinitions.add("tabSetAutoSelectTab", true).setType(Attribute_1.Attribute.BOOLEAN);
70
- attributeDefinitions.add("tabSetClassNameTabStrip", undefined).setType(Attribute_1.Attribute.STRING);
71
- attributeDefinitions.add("tabSetClassNameHeader", undefined).setType(Attribute_1.Attribute.STRING);
72
- attributeDefinitions.add("tabSetEnableTabStrip", true).setType(Attribute_1.Attribute.BOOLEAN);
73
- attributeDefinitions.add("tabSetHeaderHeight", 0).setType(Attribute_1.Attribute.NUMBER);
74
- attributeDefinitions.add("tabSetTabStripHeight", 0).setType(Attribute_1.Attribute.NUMBER);
75
- attributeDefinitions.add("tabSetMarginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
76
- .setType("IInsets");
77
- attributeDefinitions.add("tabSetBorderInsets", { top: 0, right: 0, bottom: 0, left: 0 })
78
- .setType("IInsets");
79
- attributeDefinitions.add("tabSetTabLocation", "top").setType("ITabLocation");
80
- attributeDefinitions.add("tabSetMinWidth", 0).setType(Attribute_1.Attribute.NUMBER);
81
- attributeDefinitions.add("tabSetMinHeight", 0).setType(Attribute_1.Attribute.NUMBER);
82
- // border
83
- attributeDefinitions.add("borderSize", 200).setType(Attribute_1.Attribute.NUMBER);
84
- attributeDefinitions.add("borderMinSize", 0).setType(Attribute_1.Attribute.NUMBER);
85
- attributeDefinitions.add("borderBarSize", 0).setType(Attribute_1.Attribute.NUMBER);
86
- attributeDefinitions.add("borderEnableDrop", true).setType(Attribute_1.Attribute.BOOLEAN);
87
- attributeDefinitions.add("borderAutoSelectTabWhenOpen", true).setType(Attribute_1.Attribute.BOOLEAN);
88
- attributeDefinitions.add("borderAutoSelectTabWhenClosed", false).setType(Attribute_1.Attribute.BOOLEAN);
89
- attributeDefinitions.add("borderClassName", undefined).setType(Attribute_1.Attribute.STRING);
90
- attributeDefinitions.add("borderEnableAutoHide", false).setType(Attribute_1.Attribute.BOOLEAN);
91
- return attributeDefinitions;
92
- }
93
- /**
94
- * 'private' constructor. Use the static method Model.fromJson(json) to create a model
95
- * @internal
96
- */
97
- constructor() {
98
- /** @internal */
99
- this._borderRects = { inner: Rect_1.Rect.empty(), outer: Rect_1.Rect.empty() };
100
- this._attributes = {};
101
- this._idMap = {};
102
- this._borders = new BorderSet_1.BorderSet(this);
103
- this._pointerFine = true;
104
- this._showHiddenBorder = DockLocation_1.DockLocation.CENTER;
105
- }
106
- /** @internal */
107
- _setChangeListener(listener) {
108
- this._changeListener = listener;
109
- }
110
- /**
111
- * Get the currently active tabset node
112
- */
113
- getActiveTabset() {
114
- if (this._activeTabSet && this.getNodeById(this._activeTabSet.getId())) {
115
- return this._activeTabSet;
116
- }
117
- else {
118
- return undefined;
119
- }
120
- }
121
- /** @internal */
122
- _getShowHiddenBorder() {
123
- return this._showHiddenBorder;
124
- }
125
- /** @internal */
126
- _setShowHiddenBorder(location) {
127
- this._showHiddenBorder = location;
128
- }
129
- /** @internal */
130
- _setActiveTabset(tabsetNode) {
131
- this._activeTabSet = tabsetNode;
132
- }
133
- /**
134
- * Get the currently maximized tabset node
135
- */
136
- getMaximizedTabset() {
137
- return this._maximizedTabSet;
138
- }
139
- /** @internal */
140
- _setMaximizedTabset(tabsetNode) {
141
- this._maximizedTabSet = tabsetNode;
142
- }
143
- /**
144
- * Gets the root RowNode of the model
145
- * @returns {RowNode}
146
- */
147
- getRoot() {
148
- return this._root;
149
- }
150
- isRootOrientationVertical() {
151
- return this._attributes.rootOrientationVertical;
152
- }
153
- isUseVisibility() {
154
- return this._attributes.enableUseVisibility;
155
- }
156
- isEnableRotateBorderIcons() {
157
- return this._attributes.enableRotateBorderIcons;
158
- }
159
- /**
160
- * Gets the
161
- * @returns {BorderSet|*}
162
- */
163
- getBorderSet() {
164
- return this._borders;
165
- }
166
- /** @internal */
167
- _getOuterInnerRects() {
168
- return this._borderRects;
169
- }
170
- /** @internal */
171
- _getPointerFine() {
172
- return this._pointerFine;
173
- }
174
- /** @internal */
175
- _setPointerFine(pointerFine) {
176
- this._pointerFine = pointerFine;
177
- }
178
- /**
179
- * Visits all the nodes in the model and calls the given function for each
180
- * @param fn a function that takes visited node and a integer level as parameters
181
- */
182
- visitNodes(fn) {
183
- this._borders._forEachNode(fn);
184
- this._root._forEachNode(fn, 0);
185
- }
186
- /**
187
- * Gets a node by its id
188
- * @param id the id to find
189
- */
190
- getNodeById(id) {
191
- return this._idMap[id];
192
- }
193
- /**
194
- * Finds the first/top left tab set of the given node.
195
- * @param node The top node you want to begin searching from, deafults to the root node
196
- * @returns The first Tab Set
197
- */
198
- getFirstTabSet(node = this._root) {
199
- const child = node.getChildren()[0];
200
- if (child instanceof TabSetNode_1.TabSetNode) {
201
- return child;
202
- }
203
- else {
204
- return this.getFirstTabSet(child);
205
- }
206
- }
207
- /**
208
- * Update the node tree by performing the given action,
209
- * Actions should be generated via static methods on the Actions class
210
- * @param action the action to perform
211
- * @returns added Node for Actions.addNode; undefined otherwise
212
- */
213
- doAction(action) {
214
- let returnVal = undefined;
215
- // console.log(action);
216
- switch (action.type) {
217
- case Actions_1.Actions.ADD_NODE: {
218
- const newNode = new TabNode_1.TabNode(this, action.data.json, true);
219
- const toNode = this._idMap[action.data.toNode];
220
- if (toNode instanceof TabSetNode_1.TabSetNode || toNode instanceof BorderNode_1.BorderNode || toNode instanceof RowNode_1.RowNode) {
221
- toNode.drop(newNode, DockLocation_1.DockLocation.getByName(action.data.location), action.data.index, action.data.select);
222
- returnVal = newNode;
223
- }
224
- break;
225
- }
226
- case Actions_1.Actions.MOVE_NODE: {
227
- const fromNode = this._idMap[action.data.fromNode];
228
- if (fromNode instanceof TabNode_1.TabNode || fromNode instanceof TabSetNode_1.TabSetNode) {
229
- const toNode = this._idMap[action.data.toNode];
230
- if (toNode instanceof TabSetNode_1.TabSetNode || toNode instanceof BorderNode_1.BorderNode || toNode instanceof RowNode_1.RowNode) {
231
- toNode.drop(fromNode, DockLocation_1.DockLocation.getByName(action.data.location), action.data.index, action.data.select);
232
- }
233
- }
234
- break;
235
- }
236
- case Actions_1.Actions.DELETE_TAB: {
237
- const node = this._idMap[action.data.node];
238
- if (node instanceof TabNode_1.TabNode) {
239
- node._delete();
240
- }
241
- break;
242
- }
243
- case Actions_1.Actions.DELETE_TABSET: {
244
- const node = this._idMap[action.data.node];
245
- if (node instanceof TabSetNode_1.TabSetNode) {
246
- // first delete all child tabs that are closeable
247
- const children = [...node.getChildren()];
248
- for (let i = 0; i < children.length; i++) {
249
- const child = children[i];
250
- if (child.isEnableClose()) {
251
- child._delete();
252
- }
253
- }
254
- if (node.getChildren().length === 0) {
255
- node._delete();
256
- }
257
- this._tidy();
258
- }
259
- break;
260
- }
261
- case Actions_1.Actions.FLOAT_TAB: {
262
- const node = this._idMap[action.data.node];
263
- if (node instanceof TabNode_1.TabNode) {
264
- node._setFloating(true);
265
- (0, Utils_1.adjustSelectedIndexAfterFloat)(node);
266
- }
267
- break;
268
- }
269
- case Actions_1.Actions.UNFLOAT_TAB: {
270
- const node = this._idMap[action.data.node];
271
- if (node instanceof TabNode_1.TabNode) {
272
- node._setFloating(false);
273
- (0, Utils_1.adjustSelectedIndexAfterDock)(node);
274
- }
275
- break;
276
- }
277
- case Actions_1.Actions.RENAME_TAB: {
278
- const node = this._idMap[action.data.node];
279
- if (node instanceof TabNode_1.TabNode) {
280
- node._setName(action.data.text);
281
- }
282
- break;
283
- }
284
- case Actions_1.Actions.SELECT_TAB: {
285
- const tabNode = this._idMap[action.data.tabNode];
286
- if (tabNode instanceof TabNode_1.TabNode) {
287
- const parent = tabNode.getParent();
288
- const pos = parent.getChildren().indexOf(tabNode);
289
- if (parent instanceof BorderNode_1.BorderNode) {
290
- if (parent.getSelected() === pos) {
291
- parent._setSelected(-1);
292
- }
293
- else {
294
- parent._setSelected(pos);
295
- }
296
- }
297
- else if (parent instanceof TabSetNode_1.TabSetNode) {
298
- if (parent.getSelected() !== pos) {
299
- parent._setSelected(pos);
300
- }
301
- this._activeTabSet = parent;
302
- }
303
- }
304
- break;
305
- }
306
- case Actions_1.Actions.SET_ACTIVE_TABSET: {
307
- if (action.data.tabsetNode === undefined) {
308
- this._activeTabSet = undefined;
309
- }
310
- else {
311
- const tabsetNode = this._idMap[action.data.tabsetNode];
312
- if (tabsetNode instanceof TabSetNode_1.TabSetNode) {
313
- this._activeTabSet = tabsetNode;
314
- }
315
- }
316
- break;
317
- }
318
- case Actions_1.Actions.ADJUST_SPLIT: {
319
- const node1 = this._idMap[action.data.node1];
320
- const node2 = this._idMap[action.data.node2];
321
- if ((node1 instanceof TabSetNode_1.TabSetNode || node1 instanceof RowNode_1.RowNode) && (node2 instanceof TabSetNode_1.TabSetNode || node2 instanceof RowNode_1.RowNode)) {
322
- this._adjustSplitSide(node1, action.data.weight1, action.data.pixelWidth1);
323
- this._adjustSplitSide(node2, action.data.weight2, action.data.pixelWidth2);
324
- }
325
- break;
326
- }
327
- case Actions_1.Actions.ADJUST_BORDER_SPLIT: {
328
- const node = this._idMap[action.data.node];
329
- if (node instanceof BorderNode_1.BorderNode) {
330
- node._setSize(action.data.pos);
331
- }
332
- break;
333
- }
334
- case Actions_1.Actions.MAXIMIZE_TOGGLE: {
335
- const node = this._idMap[action.data.node];
336
- if (node instanceof TabSetNode_1.TabSetNode) {
337
- if (node === this._maximizedTabSet) {
338
- this._maximizedTabSet = undefined;
339
- }
340
- else {
341
- this._maximizedTabSet = node;
342
- this._activeTabSet = node;
343
- }
344
- }
345
- break;
346
- }
347
- case Actions_1.Actions.UPDATE_MODEL_ATTRIBUTES: {
348
- this._updateAttrs(action.data.json);
349
- break;
350
- }
351
- case Actions_1.Actions.UPDATE_NODE_ATTRIBUTES: {
352
- const node = this._idMap[action.data.node];
353
- node._updateAttrs(action.data.json);
354
- break;
355
- }
356
- default:
357
- break;
358
- }
359
- this._updateIdMap();
360
- if (this._changeListener !== undefined) {
361
- this._changeListener(action);
362
- }
363
- return returnVal;
364
- }
365
- /** @internal */
366
- _updateIdMap() {
367
- // regenerate idMap to stop it building up
368
- this._idMap = {};
369
- this.visitNodes((node) => (this._idMap[node.getId()] = node));
370
- // console.log(JSON.stringify(Object.keys(this._idMap)));
371
- }
372
- /** @internal */
373
- _adjustSplitSide(node, weight, pixels) {
374
- node._setWeight(weight);
375
- if (node.getWidth() != null && node.getOrientation() === Orientation_1.Orientation.VERT) {
376
- node._updateAttrs({ width: pixels });
377
- }
378
- else if (node.getHeight() != null && node.getOrientation() === Orientation_1.Orientation.HORZ) {
379
- node._updateAttrs({ height: pixels });
380
- }
381
- }
382
- /**
383
- * Converts the model to a json object
384
- * @returns {IJsonModel} json object that represents this model
385
- */
386
- toJson() {
387
- const global = {};
388
- Model._attributeDefinitions.toJson(global, this._attributes);
389
- // save state of nodes
390
- this.visitNodes((node) => {
391
- node._fireEvent("save", undefined);
392
- });
393
- return { global, borders: this._borders._toJson(), layout: this._root.toJson() };
394
- }
395
- getSplitterSize() {
396
- let splitterSize = this._attributes.splitterSize;
397
- if (splitterSize === -1) {
398
- // use defaults
399
- splitterSize = this._pointerFine ? 8 : 12; // larger for mobile
400
- }
401
- return splitterSize;
402
- }
403
- isLegacyOverflowMenu() {
404
- return this._attributes.legacyOverflowMenu;
405
- }
406
- getSplitterExtra() {
407
- return this._attributes.splitterExtra;
408
- }
409
- isEnableEdgeDock() {
410
- return this._attributes.enableEdgeDock;
411
- }
412
- /** @internal */
413
- _addNode(node) {
414
- const id = node.getId();
415
- if (this._idMap[id] !== undefined) {
416
- throw new Error(`Error: each node must have a unique id, duplicate id:${node.getId()}`);
417
- }
418
- if (node.getType() !== "splitter") {
419
- this._idMap[id] = node;
420
- }
421
- }
422
- /** @internal */
423
- _layout(rect, metrics) {
424
- var _a;
425
- // let start = Date.now();
426
- this._borderRects = this._borders._layoutBorder({ outer: rect, inner: rect }, metrics);
427
- rect = this._borderRects.inner.removeInsets(this._getAttribute("marginInsets"));
428
- (_a = this._root) === null || _a === void 0 ? void 0 : _a.calcMinSize();
429
- this._root._layout(rect, metrics);
430
- // console.log("layout time: " + (Date.now() - start));
431
- return rect;
432
- }
433
- /** @internal */
434
- _findDropTargetNode(dragNode, x, y) {
435
- let node = this._root._findDropTargetNode(dragNode, x, y);
436
- if (node === undefined) {
437
- node = this._borders._findDropTargetNode(dragNode, x, y);
438
- }
439
- return node;
440
- }
441
- /** @internal */
442
- _tidy() {
443
- // console.log("before _tidy", this.toString());
444
- this._root._tidy();
445
- // console.log("after _tidy", this.toString());
446
- }
447
- /** @internal */
448
- _updateAttrs(json) {
449
- Model._attributeDefinitions.update(json, this._attributes);
450
- }
451
- /** @internal */
452
- _nextUniqueId() {
453
- return '#' + (0, Utils_1.randomUUID)();
454
- }
455
- /** @internal */
456
- _getAttribute(name) {
457
- return this._attributes[name];
458
- }
459
- /**
460
- * Sets a function to allow/deny dropping a node
461
- * @param onAllowDrop function that takes the drag node and DropInfo and returns true if the drop is allowed
462
- */
463
- setOnAllowDrop(onAllowDrop) {
464
- this._onAllowDrop = onAllowDrop;
465
- }
466
- /** @internal */
467
- _getOnAllowDrop() {
468
- return this._onAllowDrop;
469
- }
470
- /**
471
- * set callback called when a new TabSet is created.
472
- * The tabNode can be undefined if it's the auto created first tabset in the root row (when the last
473
- * tab is deleted, the root tabset can be recreated)
474
- * @param onCreateTabSet
475
- */
476
- setOnCreateTabSet(onCreateTabSet) {
477
- this._onCreateTabSet = onCreateTabSet;
478
- }
479
- /** @internal */
480
- _getOnCreateTabSet() {
481
- return this._onCreateTabSet;
482
- }
483
- static toTypescriptInterfaces() {
484
- console.log(Model._attributeDefinitions.toTypescriptInterface("Global", undefined));
485
- console.log(RowNode_1.RowNode.getAttributeDefinitions().toTypescriptInterface("Row", Model._attributeDefinitions));
486
- console.log(TabSetNode_1.TabSetNode.getAttributeDefinitions().toTypescriptInterface("TabSet", Model._attributeDefinitions));
487
- console.log(TabNode_1.TabNode.getAttributeDefinitions().toTypescriptInterface("Tab", Model._attributeDefinitions));
488
- console.log(BorderNode_1.BorderNode.getAttributeDefinitions().toTypescriptInterface("Border", Model._attributeDefinitions));
489
- }
490
- toString() {
491
- return JSON.stringify(this.toJson());
492
- }
493
- }
494
- exports.Model = Model;
495
- /** @internal */
496
- Model._attributeDefinitions = Model._createAttributeDefinitions();
1
+ import { Attribute } from "../Attribute";
2
+ import { AttributeDefinitions } from "../AttributeDefinitions";
3
+ import { DockLocation } from "../DockLocation";
4
+ import { Rect } from "../Rect";
5
+ import { Actions } from "./Actions";
6
+ import { BorderNode } from "./BorderNode";
7
+ import { BorderSet } from "./BorderSet";
8
+ import { RowNode } from "./RowNode";
9
+ import { TabNode } from "./TabNode";
10
+ import { TabSetNode } from "./TabSetNode";
11
+ import { randomUUID } from "./Utils";
12
+ import { LayoutWindow } from "./LayoutWindow";
13
+ import { isOnScreen } from "../view/Utils";
14
+ /** @internal */
15
+ export const DefaultMin = 0;
16
+ /** @internal */
17
+ export const DefaultMax = 99999;
18
+ /**
19
+ * Class containing the Tree of Nodes used by the FlexLayout component
20
+ */
21
+ export class Model {
22
+ /**
23
+ * 'private' constructor. Use the static method Model.fromJson(json) to create a model
24
+ * @internal
25
+ */
26
+ constructor() {
27
+ this.attributes = {};
28
+ this.idMap = new Map();
29
+ this.borders = new BorderSet(this);
30
+ this.windows = new Map();
31
+ this.rootWindow = new LayoutWindow(Model.MAIN_WINDOW_ID, Rect.empty());
32
+ this.windows.set(Model.MAIN_WINDOW_ID, this.rootWindow);
33
+ this.changeListeners = [];
34
+ }
35
+ /**
36
+ * Update the node tree by performing the given action,
37
+ * Actions should be generated via static methods on the Actions class
38
+ * @param action the action to perform
39
+ * @returns added Node for Actions.addNode, windowId for createWindow
40
+ */
41
+ doAction(action) {
42
+ var _a;
43
+ let returnVal = undefined;
44
+ // console.log(action);
45
+ switch (action.type) {
46
+ case Actions.ADD_NODE: {
47
+ const newNode = new TabNode(this, action.data.json, true);
48
+ const toNode = this.idMap.get(action.data.toNode);
49
+ if (toNode instanceof TabSetNode || toNode instanceof BorderNode || toNode instanceof RowNode) {
50
+ toNode.drop(newNode, DockLocation.getByName(action.data.location), action.data.index, action.data.select);
51
+ returnVal = newNode;
52
+ }
53
+ break;
54
+ }
55
+ case Actions.MOVE_NODE: {
56
+ const fromNode = this.idMap.get(action.data.fromNode);
57
+ if (fromNode instanceof TabNode || fromNode instanceof TabSetNode || fromNode instanceof RowNode) {
58
+ if (fromNode === this.getMaximizedTabset(fromNode.getWindowId())) {
59
+ const fromWindow = this.windows.get(fromNode.getWindowId());
60
+ fromWindow.maximizedTabSet = undefined;
61
+ }
62
+ const toNode = this.idMap.get(action.data.toNode);
63
+ if (toNode instanceof TabSetNode || toNode instanceof BorderNode || toNode instanceof RowNode) {
64
+ toNode.drop(fromNode, DockLocation.getByName(action.data.location), action.data.index, action.data.select);
65
+ }
66
+ }
67
+ this.removeEmptyWindows();
68
+ break;
69
+ }
70
+ case Actions.DELETE_TAB: {
71
+ const node = this.idMap.get(action.data.node);
72
+ if (node instanceof TabNode) {
73
+ node.delete();
74
+ }
75
+ this.removeEmptyWindows();
76
+ break;
77
+ }
78
+ case Actions.DELETE_TABSET: {
79
+ const node = this.idMap.get(action.data.node);
80
+ if (node instanceof TabSetNode) {
81
+ // first delete all child tabs that are closeable
82
+ const children = [...node.getChildren()];
83
+ for (let i = 0; i < children.length; i++) {
84
+ const child = children[i];
85
+ if (child.isEnableClose()) {
86
+ child.delete();
87
+ }
88
+ }
89
+ if (node.getChildren().length === 0) {
90
+ node.delete();
91
+ }
92
+ this.tidy();
93
+ }
94
+ this.removeEmptyWindows();
95
+ break;
96
+ }
97
+ case Actions.POPOUT_TABSET: {
98
+ const node = this.idMap.get(action.data.node);
99
+ if (node instanceof TabSetNode) {
100
+ const isMaximized = node.isMaximized();
101
+ const oldLayoutWindow = this.windows.get(node.getWindowId());
102
+ const windowId = randomUUID();
103
+ const layoutWindow = new LayoutWindow(windowId, oldLayoutWindow.toScreenRectFunction(node.getRect()));
104
+ const json = {
105
+ type: "row",
106
+ children: []
107
+ };
108
+ const row = RowNode.fromJson(json, this, layoutWindow);
109
+ layoutWindow.root = row;
110
+ this.windows.set(windowId, layoutWindow);
111
+ row.drop(node, DockLocation.CENTER, 0);
112
+ if (isMaximized) {
113
+ this.rootWindow.maximizedTabSet = undefined;
114
+ }
115
+ }
116
+ this.removeEmptyWindows();
117
+ break;
118
+ }
119
+ case Actions.POPOUT_TAB: {
120
+ const node = this.idMap.get(action.data.node);
121
+ if (node instanceof TabNode) {
122
+ const windowId = randomUUID();
123
+ let r = Rect.empty();
124
+ if (node.getParent() instanceof TabSetNode) {
125
+ r = node.getParent().getRect();
126
+ }
127
+ else {
128
+ r = node.getParent().getContentRect();
129
+ }
130
+ const oldLayoutWindow = this.windows.get(node.getWindowId());
131
+ const layoutWindow = new LayoutWindow(windowId, oldLayoutWindow.toScreenRectFunction(r));
132
+ const tabsetId = randomUUID();
133
+ const json = {
134
+ type: "row",
135
+ children: [
136
+ { type: "tabset", id: tabsetId }
137
+ ]
138
+ };
139
+ const row = RowNode.fromJson(json, this, layoutWindow);
140
+ layoutWindow.root = row;
141
+ this.windows.set(windowId, layoutWindow);
142
+ const tabset = this.idMap.get(tabsetId);
143
+ tabset.drop(node, DockLocation.CENTER, 0, true);
144
+ }
145
+ this.removeEmptyWindows();
146
+ break;
147
+ }
148
+ case Actions.CLOSE_WINDOW: {
149
+ const window = this.windows.get(action.data.windowId);
150
+ if (window) {
151
+ (_a = this.rootWindow.root) === null || _a === void 0 ? void 0 : _a.drop(window === null || window === void 0 ? void 0 : window.root, DockLocation.CENTER, -1);
152
+ this.rootWindow.visitNodes((node, level) => {
153
+ if (node instanceof RowNode) {
154
+ node.setWindowId(Model.MAIN_WINDOW_ID);
155
+ }
156
+ });
157
+ // this.getFirstTabSet().drop(window?.root!,DockLocation.CENTER, -1);
158
+ this.windows.delete(action.data.windowId);
159
+ }
160
+ break;
161
+ }
162
+ case Actions.CREATE_WINDOW: {
163
+ const windowId = randomUUID();
164
+ const layoutWindow = new LayoutWindow(windowId, Rect.fromJson(action.data.rect));
165
+ const row = RowNode.fromJson(action.data.layout, this, layoutWindow);
166
+ layoutWindow.root = row;
167
+ this.windows.set(windowId, layoutWindow);
168
+ returnVal = windowId;
169
+ break;
170
+ }
171
+ case Actions.RENAME_TAB: {
172
+ const node = this.idMap.get(action.data.node);
173
+ if (node instanceof TabNode) {
174
+ node.setName(action.data.text);
175
+ }
176
+ break;
177
+ }
178
+ case Actions.SELECT_TAB: {
179
+ const tabNode = this.idMap.get(action.data.tabNode);
180
+ const windowId = action.data.windowId ? action.data.windowId : Model.MAIN_WINDOW_ID;
181
+ const window = this.windows.get(windowId);
182
+ if (tabNode instanceof TabNode) {
183
+ const parent = tabNode.getParent();
184
+ const pos = parent.getChildren().indexOf(tabNode);
185
+ if (parent instanceof BorderNode) {
186
+ if (parent.getSelected() === pos) {
187
+ parent.setSelected(-1);
188
+ }
189
+ else {
190
+ parent.setSelected(pos);
191
+ }
192
+ }
193
+ else if (parent instanceof TabSetNode) {
194
+ if (parent.getSelected() !== pos) {
195
+ parent.setSelected(pos);
196
+ }
197
+ window.activeTabSet = parent;
198
+ }
199
+ }
200
+ break;
201
+ }
202
+ case Actions.SET_ACTIVE_TABSET: {
203
+ const windowId = action.data.windowId ? action.data.windowId : Model.MAIN_WINDOW_ID;
204
+ const window = this.windows.get(windowId);
205
+ if (action.data.tabsetNode === undefined) {
206
+ window.activeTabSet = undefined;
207
+ }
208
+ else {
209
+ const tabsetNode = this.idMap.get(action.data.tabsetNode);
210
+ if (tabsetNode instanceof TabSetNode) {
211
+ window.activeTabSet = tabsetNode;
212
+ }
213
+ }
214
+ break;
215
+ }
216
+ case Actions.ADJUST_WEIGHTS: {
217
+ const row = this.idMap.get(action.data.nodeId);
218
+ const c = row.getChildren();
219
+ for (let i = 0; i < c.length; i++) {
220
+ const n = c[i];
221
+ n.setWeight(action.data.weights[i]);
222
+ }
223
+ break;
224
+ }
225
+ case Actions.ADJUST_BORDER_SPLIT: {
226
+ const node = this.idMap.get(action.data.node);
227
+ if (node instanceof BorderNode) {
228
+ node.setSize(action.data.pos);
229
+ }
230
+ break;
231
+ }
232
+ case Actions.MAXIMIZE_TOGGLE: {
233
+ const windowId = action.data.windowId ? action.data.windowId : Model.MAIN_WINDOW_ID;
234
+ const window = this.windows.get(windowId);
235
+ const node = this.idMap.get(action.data.node);
236
+ if (node instanceof TabSetNode) {
237
+ if (node === window.maximizedTabSet) {
238
+ window.maximizedTabSet = undefined;
239
+ }
240
+ else {
241
+ window.maximizedTabSet = node;
242
+ window.activeTabSet = node;
243
+ }
244
+ }
245
+ break;
246
+ }
247
+ case Actions.UPDATE_MODEL_ATTRIBUTES: {
248
+ this.updateAttrs(action.data.json);
249
+ break;
250
+ }
251
+ case Actions.UPDATE_NODE_ATTRIBUTES: {
252
+ const node = this.idMap.get(action.data.node);
253
+ node.updateAttrs(action.data.json);
254
+ break;
255
+ }
256
+ default:
257
+ break;
258
+ }
259
+ this.updateIdMap();
260
+ for (const listener of this.changeListeners) {
261
+ listener(action);
262
+ }
263
+ return returnVal;
264
+ }
265
+ /**
266
+ * Get the currently active tabset node
267
+ */
268
+ getActiveTabset(windowId = Model.MAIN_WINDOW_ID) {
269
+ const window = this.windows.get(windowId);
270
+ if (window && window.activeTabSet && this.getNodeById(window.activeTabSet.getId())) {
271
+ return window.activeTabSet;
272
+ }
273
+ else {
274
+ return undefined;
275
+ }
276
+ }
277
+ /**
278
+ * Get the currently maximized tabset node
279
+ */
280
+ getMaximizedTabset(windowId = Model.MAIN_WINDOW_ID) {
281
+ return this.windows.get(windowId).maximizedTabSet;
282
+ }
283
+ /**
284
+ * Gets the root RowNode of the model
285
+ * @returns {RowNode}
286
+ */
287
+ getRoot(windowId = Model.MAIN_WINDOW_ID) {
288
+ return this.windows.get(windowId).root;
289
+ }
290
+ isRootOrientationVertical() {
291
+ return this.attributes.rootOrientationVertical;
292
+ }
293
+ isEnableRotateBorderIcons() {
294
+ return this.attributes.enableRotateBorderIcons;
295
+ }
296
+ /**
297
+ * Gets the
298
+ * @returns {BorderSet|*}
299
+ */
300
+ getBorderSet() {
301
+ return this.borders;
302
+ }
303
+ getwindowsMap() {
304
+ return this.windows;
305
+ }
306
+ /**
307
+ * Visits all the nodes in the model and calls the given function for each
308
+ * @param fn a function that takes visited node and a integer level as parameters
309
+ */
310
+ visitNodes(fn) {
311
+ this.borders.forEachNode(fn);
312
+ for (const [_, w] of this.windows) {
313
+ w.root.forEachNode(fn, 0);
314
+ }
315
+ }
316
+ visitWindowNodes(windowId, fn) {
317
+ if (this.windows.has(windowId)) {
318
+ if (windowId === Model.MAIN_WINDOW_ID) {
319
+ this.borders.forEachNode(fn);
320
+ }
321
+ this.windows.get(windowId).visitNodes(fn);
322
+ }
323
+ }
324
+ /**
325
+ * Gets a node by its id
326
+ * @param id the id to find
327
+ */
328
+ getNodeById(id) {
329
+ return this.idMap.get(id);
330
+ }
331
+ /**
332
+ * Finds the first/top left tab set of the given node.
333
+ * @param node The top node you want to begin searching from, deafults to the root node
334
+ * @returns The first Tab Set
335
+ */
336
+ getFirstTabSet(node = this.windows.get(Model.MAIN_WINDOW_ID).root) {
337
+ const child = node.getChildren()[0];
338
+ if (child instanceof TabSetNode) {
339
+ return child;
340
+ }
341
+ else {
342
+ return this.getFirstTabSet(child);
343
+ }
344
+ }
345
+ /**
346
+ * Loads the model from the given json object
347
+ * @param json the json model to load
348
+ * @returns {Model} a new Model object
349
+ */
350
+ static fromJson(json) {
351
+ const model = new Model();
352
+ Model.attributeDefinitions.fromJson(json.global, model.attributes);
353
+ if (json.borders) {
354
+ model.borders = BorderSet.fromJson(json.borders, model);
355
+ }
356
+ if (json.popouts) {
357
+ let i = 0;
358
+ let top = 100;
359
+ let left = 100;
360
+ for (const windowId in json.popouts) {
361
+ const windowJson = json.popouts[windowId];
362
+ const layoutWindow = LayoutWindow.fromJson(windowJson, model, windowId);
363
+ model.windows.set(windowId, layoutWindow);
364
+ // offscreen windows will reload cascaded (since cannot reposition)
365
+ if (!isOnScreen(layoutWindow.rect)) {
366
+ layoutWindow.rect = new Rect(top + i * 50, left + i * 50, 600, 400);
367
+ i++;
368
+ }
369
+ }
370
+ }
371
+ model.rootWindow.root = RowNode.fromJson(json.layout, model, model.getwindowsMap().get(Model.MAIN_WINDOW_ID));
372
+ model.tidy(); // initial tidy of node tree
373
+ return model;
374
+ }
375
+ /**
376
+ * Converts the model to a json object
377
+ * @returns {IJsonModel} json object that represents this model
378
+ */
379
+ toJson() {
380
+ const global = {};
381
+ Model.attributeDefinitions.toJson(global, this.attributes);
382
+ // save state of nodes
383
+ this.visitNodes((node) => {
384
+ node.fireEvent("save", {});
385
+ });
386
+ const windows = {};
387
+ for (const [id, window] of this.windows) {
388
+ if (id !== Model.MAIN_WINDOW_ID) {
389
+ windows[id] = window.toJson();
390
+ }
391
+ }
392
+ return {
393
+ global,
394
+ borders: this.borders.toJson(),
395
+ layout: this.rootWindow.root.toJson(),
396
+ popouts: windows
397
+ };
398
+ }
399
+ getSplitterSize() {
400
+ return this.attributes.splitterSize;
401
+ }
402
+ getSplitterExtra() {
403
+ return this.attributes.splitterExtra;
404
+ }
405
+ isEnableEdgeDock() {
406
+ return this.attributes.enableEdgeDock;
407
+ }
408
+ isSplitterEnableHandle() {
409
+ return this.attributes.splitterEnableHandle;
410
+ }
411
+ /**
412
+ * Sets a function to allow/deny dropping a node
413
+ * @param onAllowDrop function that takes the drag node and DropInfo and returns true if the drop is allowed
414
+ */
415
+ setOnAllowDrop(onAllowDrop) {
416
+ this.onAllowDrop = onAllowDrop;
417
+ }
418
+ /**
419
+ * set callback called when a new TabSet is created.
420
+ * The tabNode can be undefined if it's the auto created first tabset in the root row (when the last
421
+ * tab is deleted, the root tabset can be recreated)
422
+ * @param onCreateTabSet
423
+ */
424
+ setOnCreateTabSet(onCreateTabSet) {
425
+ this.onCreateTabSet = onCreateTabSet;
426
+ }
427
+ addChangeListener(listener) {
428
+ this.changeListeners.push(listener);
429
+ }
430
+ removeChangeListener(listener) {
431
+ const pos = this.changeListeners.findIndex(l => l === listener);
432
+ if (pos !== -1) {
433
+ this.changeListeners.splice(pos, 1);
434
+ }
435
+ }
436
+ toString() {
437
+ return JSON.stringify(this.toJson());
438
+ }
439
+ /***********************internal ********************************/
440
+ /** @internal */
441
+ removeEmptyWindows() {
442
+ const emptyWindows = new Set();
443
+ for (const [windowId] of this.windows) {
444
+ if (windowId !== Model.MAIN_WINDOW_ID) {
445
+ let count = 0;
446
+ this.visitWindowNodes(windowId, (node) => {
447
+ if (node instanceof TabNode) {
448
+ count++;
449
+ }
450
+ });
451
+ if (count === 0) {
452
+ emptyWindows.add(windowId);
453
+ }
454
+ }
455
+ }
456
+ for (const windowId of emptyWindows) {
457
+ this.windows.delete(windowId);
458
+ }
459
+ }
460
+ /** @internal */
461
+ setActiveTabset(tabsetNode, windowId) {
462
+ const window = this.windows.get(windowId);
463
+ if (window) {
464
+ if (tabsetNode) {
465
+ window.activeTabSet = tabsetNode;
466
+ }
467
+ else {
468
+ window.activeTabSet = undefined;
469
+ }
470
+ }
471
+ }
472
+ /** @internal */
473
+ setMaximizedTabset(tabsetNode, windowId) {
474
+ const window = this.windows.get(windowId);
475
+ if (window) {
476
+ if (tabsetNode) {
477
+ window.maximizedTabSet = tabsetNode;
478
+ }
479
+ else {
480
+ window.maximizedTabSet = undefined;
481
+ }
482
+ }
483
+ }
484
+ /** @internal */
485
+ updateIdMap() {
486
+ // regenerate idMap to stop it building up
487
+ this.idMap.clear();
488
+ this.visitNodes((node) => {
489
+ this.idMap.set(node.getId(), node);
490
+ // if (node instanceof RowNode) {
491
+ // node.normalizeWeights();
492
+ // }
493
+ });
494
+ // console.log(JSON.stringify(Object.keys(this._idMap)));
495
+ }
496
+ /** @internal */
497
+ addNode(node) {
498
+ const id = node.getId();
499
+ if (this.idMap.has(id)) {
500
+ throw new Error(`Error: each node must have a unique id, duplicate id:${node.getId()}`);
501
+ }
502
+ this.idMap.set(id, node);
503
+ }
504
+ /** @internal */
505
+ findDropTargetNode(windowId, dragNode, x, y) {
506
+ let node = this.windows.get(windowId).root.findDropTargetNode(windowId, dragNode, x, y);
507
+ if (node === undefined && windowId === Model.MAIN_WINDOW_ID) {
508
+ node = this.borders.findDropTargetNode(dragNode, x, y);
509
+ }
510
+ return node;
511
+ }
512
+ /** @internal */
513
+ tidy() {
514
+ // console.log("before _tidy", this.toString());
515
+ for (const [_, window] of this.windows) {
516
+ window.root.tidy();
517
+ }
518
+ // console.log("after _tidy", this.toString());
519
+ }
520
+ /** @internal */
521
+ updateAttrs(json) {
522
+ Model.attributeDefinitions.update(json, this.attributes);
523
+ }
524
+ /** @internal */
525
+ nextUniqueId() {
526
+ return '#' + randomUUID();
527
+ }
528
+ /** @internal */
529
+ getAttribute(name) {
530
+ return this.attributes[name];
531
+ }
532
+ /** @internal */
533
+ getOnAllowDrop() {
534
+ return this.onAllowDrop;
535
+ }
536
+ /** @internal */
537
+ getOnCreateTabSet() {
538
+ return this.onCreateTabSet;
539
+ }
540
+ static toTypescriptInterfaces() {
541
+ Model.attributeDefinitions.pairAttributes("RowNode", RowNode.getAttributeDefinitions());
542
+ Model.attributeDefinitions.pairAttributes("TabSetNode", TabSetNode.getAttributeDefinitions());
543
+ Model.attributeDefinitions.pairAttributes("TabNode", TabNode.getAttributeDefinitions());
544
+ Model.attributeDefinitions.pairAttributes("BorderNode", BorderNode.getAttributeDefinitions());
545
+ let sb = [];
546
+ sb.push(Model.attributeDefinitions.toTypescriptInterface("Global", undefined));
547
+ sb.push(RowNode.getAttributeDefinitions().toTypescriptInterface("Row", Model.attributeDefinitions));
548
+ sb.push(TabSetNode.getAttributeDefinitions().toTypescriptInterface("TabSet", Model.attributeDefinitions));
549
+ sb.push(TabNode.getAttributeDefinitions().toTypescriptInterface("Tab", Model.attributeDefinitions));
550
+ sb.push(BorderNode.getAttributeDefinitions().toTypescriptInterface("Border", Model.attributeDefinitions));
551
+ console.log(sb.join("\n"));
552
+ }
553
+ /** @internal */
554
+ static createAttributeDefinitions() {
555
+ const attributeDefinitions = new AttributeDefinitions();
556
+ attributeDefinitions.add("enableEdgeDock", true).setType(Attribute.BOOLEAN).setDescription(`enable docking to the edges of the layout, this will show the edge indicators`);
557
+ attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute.BOOLEAN).setDescription(`the top level 'row' will layout horizontally by default, set this option true to make it layout vertically`);
558
+ attributeDefinitions.add("enableRotateBorderIcons", true).setType(Attribute.BOOLEAN).setDescription(`boolean indicating if tab icons should rotate with the text in the left and right borders`);
559
+ // splitter
560
+ attributeDefinitions.add("splitterSize", 8).setType(Attribute.NUMBER).setDescription(`width in pixels of all splitters between tabsets/borders`);
561
+ attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER).setDescription(`additional width in pixels of the splitter hit test area`);
562
+ attributeDefinitions.add("splitterEnableHandle", false).setType(Attribute.BOOLEAN).setDescription(`enable a small centralized handle on all splitters`);
563
+ // tab
564
+ attributeDefinitions.add("tabEnableClose", true).setType(Attribute.BOOLEAN);
565
+ attributeDefinitions.add("tabCloseType", 1).setType("ICloseType");
566
+ attributeDefinitions.add("tabEnablePopout", false).setType(Attribute.BOOLEAN).setAlias("tabEnableFloat");
567
+ attributeDefinitions.add("tabEnablePopoutIcon", true).setType(Attribute.BOOLEAN);
568
+ attributeDefinitions.add("tabEnablePopoutOverlay", false).setType(Attribute.BOOLEAN);
569
+ attributeDefinitions.add("tabEnableDrag", true).setType(Attribute.BOOLEAN);
570
+ attributeDefinitions.add("tabEnableRename", true).setType(Attribute.BOOLEAN);
571
+ attributeDefinitions.add("tabContentClassName", undefined).setType(Attribute.STRING);
572
+ attributeDefinitions.add("tabClassName", undefined).setType(Attribute.STRING);
573
+ attributeDefinitions.add("tabIcon", undefined).setType(Attribute.STRING);
574
+ attributeDefinitions.add("tabEnableRenderOnDemand", true).setType(Attribute.BOOLEAN);
575
+ attributeDefinitions.add("tabDragSpeed", 0.3).setType(Attribute.NUMBER);
576
+ attributeDefinitions.add("tabBorderWidth", -1).setType(Attribute.NUMBER);
577
+ attributeDefinitions.add("tabBorderHeight", -1).setType(Attribute.NUMBER);
578
+ // tabset
579
+ attributeDefinitions.add("tabSetEnableDeleteWhenEmpty", true).setType(Attribute.BOOLEAN);
580
+ attributeDefinitions.add("tabSetEnableDrop", true).setType(Attribute.BOOLEAN);
581
+ attributeDefinitions.add("tabSetEnableDrag", true).setType(Attribute.BOOLEAN);
582
+ attributeDefinitions.add("tabSetEnableDivide", true).setType(Attribute.BOOLEAN);
583
+ attributeDefinitions.add("tabSetEnableMaximize", true).setType(Attribute.BOOLEAN);
584
+ attributeDefinitions.add("tabSetEnableClose", false).setType(Attribute.BOOLEAN);
585
+ attributeDefinitions.add("tabSetEnableSingleTabStretch", false).setType(Attribute.BOOLEAN);
586
+ attributeDefinitions.add("tabSetAutoSelectTab", true).setType(Attribute.BOOLEAN);
587
+ attributeDefinitions.add("tabSetEnableActiveIcon", false).setType(Attribute.BOOLEAN);
588
+ attributeDefinitions.add("tabSetClassNameTabStrip", undefined).setType(Attribute.STRING);
589
+ attributeDefinitions.add("tabSetEnableTabStrip", true).setType(Attribute.BOOLEAN);
590
+ attributeDefinitions.add("tabSetEnableTabWrap", false).setType(Attribute.BOOLEAN);
591
+ attributeDefinitions.add("tabSetTabLocation", "top").setType("ITabLocation");
592
+ attributeDefinitions.add("tabMinWidth", DefaultMin).setType(Attribute.NUMBER);
593
+ attributeDefinitions.add("tabMinHeight", DefaultMin).setType(Attribute.NUMBER);
594
+ attributeDefinitions.add("tabSetMinWidth", DefaultMin).setType(Attribute.NUMBER);
595
+ attributeDefinitions.add("tabSetMinHeight", DefaultMin).setType(Attribute.NUMBER);
596
+ attributeDefinitions.add("tabMaxWidth", DefaultMax).setType(Attribute.NUMBER);
597
+ attributeDefinitions.add("tabMaxHeight", DefaultMax).setType(Attribute.NUMBER);
598
+ attributeDefinitions.add("tabSetMaxWidth", DefaultMax).setType(Attribute.NUMBER);
599
+ attributeDefinitions.add("tabSetMaxHeight", DefaultMax).setType(Attribute.NUMBER);
600
+ // border
601
+ attributeDefinitions.add("borderSize", 200).setType(Attribute.NUMBER);
602
+ attributeDefinitions.add("borderMinSize", DefaultMin).setType(Attribute.NUMBER);
603
+ attributeDefinitions.add("borderMaxSize", DefaultMax).setType(Attribute.NUMBER);
604
+ attributeDefinitions.add("borderEnableDrop", true).setType(Attribute.BOOLEAN);
605
+ attributeDefinitions.add("borderAutoSelectTabWhenOpen", true).setType(Attribute.BOOLEAN);
606
+ attributeDefinitions.add("borderAutoSelectTabWhenClosed", false).setType(Attribute.BOOLEAN);
607
+ attributeDefinitions.add("borderClassName", undefined).setType(Attribute.STRING);
608
+ attributeDefinitions.add("borderEnableAutoHide", false).setType(Attribute.BOOLEAN);
609
+ return attributeDefinitions;
610
+ }
611
+ }
612
+ Model.MAIN_WINDOW_ID = "__main_window_id__";
613
+ /** @internal */
614
+ Model.attributeDefinitions = Model.createAttributeDefinitions();
497
615
  //# sourceMappingURL=Model.js.map