@datagrok-libraries/dock-spawn-dg 0.0.1

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 (222) hide show
  1. package/.eslintrc.json +47 -0
  2. package/CHANGELOG.md +355 -0
  3. package/LICENSE +21 -0
  4. package/README.md +11 -0
  5. package/css/dock-manager-context-menu.css +19 -0
  6. package/css/dock-manager-style.css +190 -0
  7. package/css/dock-manager.css +411 -0
  8. package/images/close.svg +6 -0
  9. package/images/dock_bottom.png +0 -0
  10. package/images/dock_bottom_sel.png +0 -0
  11. package/images/dock_fill.png +0 -0
  12. package/images/dock_fill_sel.png +0 -0
  13. package/images/dock_left.png +0 -0
  14. package/images/dock_left_sel.png +0 -0
  15. package/images/dock_right.png +0 -0
  16. package/images/dock_right_sel.png +0 -0
  17. package/images/dock_top.png +0 -0
  18. package/images/dock_top_sel.png +0 -0
  19. package/index.ts +32 -0
  20. package/lib/BrowserDialogHelper.d.ts +8 -0
  21. package/lib/BrowserDialogHelper.d.ts.map +1 -0
  22. package/lib/BrowserDialogHelper.js +60 -0
  23. package/lib/ContainerType.d.ts +7 -0
  24. package/lib/ContainerType.d.ts.map +1 -0
  25. package/lib/ContainerType.js +7 -0
  26. package/lib/Dialog.d.ts +51 -0
  27. package/lib/Dialog.d.ts.map +1 -0
  28. package/lib/Dialog.js +209 -0
  29. package/lib/DockConfig.d.ts +9 -0
  30. package/lib/DockConfig.d.ts.map +1 -0
  31. package/lib/DockConfig.js +14 -0
  32. package/lib/DockGraphDeserializer.d.ts +19 -0
  33. package/lib/DockGraphDeserializer.d.ts.map +1 -0
  34. package/lib/DockGraphDeserializer.js +114 -0
  35. package/lib/DockGraphSerializer.d.ts +14 -0
  36. package/lib/DockGraphSerializer.d.ts.map +1 -0
  37. package/lib/DockGraphSerializer.js +40 -0
  38. package/lib/DockLayoutEngine.d.ts +36 -0
  39. package/lib/DockLayoutEngine.d.ts.map +1 -0
  40. package/lib/DockLayoutEngine.js +323 -0
  41. package/lib/DockManager.d.ts +155 -0
  42. package/lib/DockManager.d.ts.map +1 -0
  43. package/lib/DockManager.js +752 -0
  44. package/lib/DockManagerContext.d.ts +10 -0
  45. package/lib/DockManagerContext.d.ts.map +1 -0
  46. package/lib/DockManagerContext.js +12 -0
  47. package/lib/DockModel.d.ts +9 -0
  48. package/lib/DockModel.d.ts.map +1 -0
  49. package/lib/DockModel.js +8 -0
  50. package/lib/DockNode.d.ts +16 -0
  51. package/lib/DockNode.d.ts.map +1 -0
  52. package/lib/DockNode.js +64 -0
  53. package/lib/DockWheel.d.ts +41 -0
  54. package/lib/DockWheel.d.ts.map +1 -0
  55. package/lib/DockWheel.js +208 -0
  56. package/lib/DockWheelItem.d.ts +16 -0
  57. package/lib/DockWheelItem.d.ts.map +1 -0
  58. package/lib/DockWheelItem.js +34 -0
  59. package/lib/DocumentManagerContainer.d.ts +16 -0
  60. package/lib/DocumentManagerContainer.d.ts.map +1 -0
  61. package/lib/DocumentManagerContainer.js +28 -0
  62. package/lib/DocumentTabPage.d.ts +11 -0
  63. package/lib/DocumentTabPage.d.ts.map +1 -0
  64. package/lib/DocumentTabPage.js +26 -0
  65. package/lib/DraggableContainer.d.ts +51 -0
  66. package/lib/DraggableContainer.d.ts.map +1 -0
  67. package/lib/DraggableContainer.js +145 -0
  68. package/lib/EventHandler.d.ts +8 -0
  69. package/lib/EventHandler.d.ts.map +1 -0
  70. package/lib/EventHandler.js +14 -0
  71. package/lib/FillDockContainer.d.ts +34 -0
  72. package/lib/FillDockContainer.d.ts.map +1 -0
  73. package/lib/FillDockContainer.js +80 -0
  74. package/lib/HorizontalDockContainer.d.ts +7 -0
  75. package/lib/HorizontalDockContainer.d.ts.map +1 -0
  76. package/lib/HorizontalDockContainer.js +9 -0
  77. package/lib/PanelContainer.d.ts +114 -0
  78. package/lib/PanelContainer.d.ts.map +1 -0
  79. package/lib/PanelContainer.js +517 -0
  80. package/lib/Point.d.ts +6 -0
  81. package/lib/Point.d.ts.map +1 -0
  82. package/lib/Point.js +8 -0
  83. package/lib/ResizableContainer.d.ts +56 -0
  84. package/lib/ResizableContainer.d.ts.map +1 -0
  85. package/lib/ResizableContainer.js +254 -0
  86. package/lib/ResizeHandle.d.ts +16 -0
  87. package/lib/ResizeHandle.d.ts.map +1 -0
  88. package/lib/ResizeHandle.js +58 -0
  89. package/lib/SplitterBar.d.ts +33 -0
  90. package/lib/SplitterBar.d.ts.map +1 -0
  91. package/lib/SplitterBar.js +137 -0
  92. package/lib/SplitterDockContainer.d.ts +36 -0
  93. package/lib/SplitterDockContainer.d.ts.map +1 -0
  94. package/lib/SplitterDockContainer.js +75 -0
  95. package/lib/SplitterPanel.d.ts +27 -0
  96. package/lib/SplitterPanel.d.ts.map +1 -0
  97. package/lib/SplitterPanel.js +195 -0
  98. package/lib/TabHandle.d.ts +56 -0
  99. package/lib/TabHandle.d.ts.map +1 -0
  100. package/lib/TabHandle.js +292 -0
  101. package/lib/TabHost.d.ts +47 -0
  102. package/lib/TabHost.d.ts.map +1 -0
  103. package/lib/TabHost.js +238 -0
  104. package/lib/TabPage.d.ts +20 -0
  105. package/lib/TabPage.d.ts.map +1 -0
  106. package/lib/TabPage.js +81 -0
  107. package/lib/UndockInitiator.d.ts +32 -0
  108. package/lib/UndockInitiator.d.ts.map +1 -0
  109. package/lib/UndockInitiator.js +152 -0
  110. package/lib/Utils.d.ts +15 -0
  111. package/lib/Utils.d.ts.map +1 -0
  112. package/lib/Utils.js +69 -0
  113. package/lib/VerticalDockContainer.d.ts +7 -0
  114. package/lib/VerticalDockContainer.d.ts.map +1 -0
  115. package/lib/VerticalDockContainer.js +9 -0
  116. package/lib/enums/PanelType.d.ts +5 -0
  117. package/lib/enums/PanelType.d.ts.map +1 -0
  118. package/lib/enums/PanelType.js +5 -0
  119. package/lib/enums/TabHostDirection.d.ts +7 -0
  120. package/lib/enums/TabHostDirection.d.ts.map +1 -0
  121. package/lib/enums/TabHostDirection.js +7 -0
  122. package/lib/enums/WheelTypes.d.ts +12 -0
  123. package/lib/enums/WheelTypes.d.ts.map +1 -0
  124. package/lib/enums/WheelTypes.js +14 -0
  125. package/lib/i18n/Defaults.d.ts +12 -0
  126. package/lib/i18n/Defaults.d.ts.map +1 -0
  127. package/lib/i18n/Defaults.js +9 -0
  128. package/lib/i18n/Localizer.d.ts +7 -0
  129. package/lib/i18n/Localizer.d.ts.map +1 -0
  130. package/lib/i18n/Localizer.js +16 -0
  131. package/lib/index.d.ts +33 -0
  132. package/lib/index.d.ts.map +1 -0
  133. package/lib/index.js +32 -0
  134. package/lib/interfaces/IDockContainer.d.ts +26 -0
  135. package/lib/interfaces/IDockContainer.d.ts.map +1 -0
  136. package/lib/interfaces/IDockContainer.js +1 -0
  137. package/lib/interfaces/IDockContainerWithSize.d.ts +6 -0
  138. package/lib/interfaces/IDockContainerWithSize.d.ts.map +1 -0
  139. package/lib/interfaces/IDockContainerWithSize.js +1 -0
  140. package/lib/interfaces/ILayoutEventListener.d.ts +27 -0
  141. package/lib/interfaces/ILayoutEventListener.d.ts.map +1 -0
  142. package/lib/interfaces/ILayoutEventListener.js +1 -0
  143. package/lib/interfaces/IMouseOrTouchEvent.d.ts +7 -0
  144. package/lib/interfaces/IMouseOrTouchEvent.d.ts.map +1 -0
  145. package/lib/interfaces/IMouseOrTouchEvent.js +1 -0
  146. package/lib/interfaces/INodeInfo.d.ts +8 -0
  147. package/lib/interfaces/INodeInfo.d.ts.map +1 -0
  148. package/lib/interfaces/INodeInfo.js +1 -0
  149. package/lib/interfaces/IPanelInfo.d.ts +10 -0
  150. package/lib/interfaces/IPanelInfo.d.ts.map +1 -0
  151. package/lib/interfaces/IPanelInfo.js +1 -0
  152. package/lib/interfaces/IRectangle.d.ts +7 -0
  153. package/lib/interfaces/IRectangle.d.ts.map +1 -0
  154. package/lib/interfaces/IRectangle.js +1 -0
  155. package/lib/interfaces/ISize.d.ts +5 -0
  156. package/lib/interfaces/ISize.d.ts.map +1 -0
  157. package/lib/interfaces/ISize.js +1 -0
  158. package/lib/interfaces/IState.d.ts +12 -0
  159. package/lib/interfaces/IState.d.ts.map +1 -0
  160. package/lib/interfaces/IState.js +1 -0
  161. package/lib/interfaces/IThickness.d.ts +7 -0
  162. package/lib/interfaces/IThickness.d.ts.map +1 -0
  163. package/lib/interfaces/IThickness.js +1 -0
  164. package/lib/webcomponent/DockSpawnTsWebcomponent.d.ts +35 -0
  165. package/lib/webcomponent/DockSpawnTsWebcomponent.d.ts.map +1 -0
  166. package/lib/webcomponent/DockSpawnTsWebcomponent.js +209 -0
  167. package/lib/webcomponent/styles.d.ts +5 -0
  168. package/lib/webcomponent/styles.d.ts.map +1 -0
  169. package/lib/webcomponent/styles.js +537 -0
  170. package/package.json +36 -0
  171. package/src/BrowserDialogHelper.ts +76 -0
  172. package/src/ContainerType.ts +6 -0
  173. package/src/Dialog.ts +253 -0
  174. package/src/DockConfig.ts +15 -0
  175. package/src/DockGraphDeserializer.ts +129 -0
  176. package/src/DockGraphSerializer.ts +53 -0
  177. package/src/DockLayoutEngine.ts +370 -0
  178. package/src/DockManager.ts +880 -0
  179. package/src/DockManagerContext.ts +16 -0
  180. package/src/DockModel.ts +12 -0
  181. package/src/DockNode.ts +81 -0
  182. package/src/DockWheel.ts +215 -0
  183. package/src/DockWheelItem.ts +41 -0
  184. package/src/DocumentManagerContainer.ts +39 -0
  185. package/src/DocumentTabPage.ts +35 -0
  186. package/src/DraggableContainer.ts +177 -0
  187. package/src/EventHandler.ts +17 -0
  188. package/src/FillDockContainer.ts +98 -0
  189. package/src/HorizontalDockContainer.ts +13 -0
  190. package/src/PanelContainer.ts +596 -0
  191. package/src/Point.ts +10 -0
  192. package/src/ResizableContainer.ts +293 -0
  193. package/src/ResizeHandle.ts +59 -0
  194. package/src/SplitterBar.ts +157 -0
  195. package/src/SplitterDockContainer.ts +95 -0
  196. package/src/SplitterPanel.ts +228 -0
  197. package/src/TabHandle.ts +347 -0
  198. package/src/TabHost.ts +267 -0
  199. package/src/TabPage.ts +98 -0
  200. package/src/UndockInitiator.ts +181 -0
  201. package/src/Utils.ts +85 -0
  202. package/src/VerticalDockContainer.ts +13 -0
  203. package/src/enums/PanelType.ts +4 -0
  204. package/src/enums/TabHostDirection.ts +6 -0
  205. package/src/enums/WheelTypes.ts +14 -0
  206. package/src/i18n/Defaults.ts +20 -0
  207. package/src/i18n/Localizer.ts +23 -0
  208. package/src/index.ts +32 -0
  209. package/src/interfaces/IDockContainer.ts +27 -0
  210. package/src/interfaces/IDockContainerWithSize.ts +6 -0
  211. package/src/interfaces/ILayoutEventListener.ts +28 -0
  212. package/src/interfaces/IMouseOrTouchEvent.ts +6 -0
  213. package/src/interfaces/INodeInfo.ts +8 -0
  214. package/src/interfaces/IPanelInfo.ts +10 -0
  215. package/src/interfaces/IRectangle.ts +6 -0
  216. package/src/interfaces/ISize.ts +4 -0
  217. package/src/interfaces/IState.ts +12 -0
  218. package/src/interfaces/IThickness.ts +6 -0
  219. package/src/webcomponent/DockSpawnTsWebcomponent.ts +248 -0
  220. package/src/webcomponent/styles.ts +544 -0
  221. package/tsconfig.json +74 -0
  222. package/tsconfig.tsbuildinfo +1 -0
package/src/Point.ts ADDED
@@ -0,0 +1,10 @@
1
+ export class Point {
2
+
3
+ x: number;
4
+ y: number;
5
+
6
+ constructor(x: number, y: number) {
7
+ this.x = x;
8
+ this.y = y;
9
+ }
10
+ }
@@ -0,0 +1,293 @@
1
+ import { Dialog } from "./Dialog.js";
2
+ import { ResizeHandle } from "./ResizeHandle.js";
3
+ import { EventHandler } from "./EventHandler.js";
4
+ import { DockManager } from "./DockManager.js";
5
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
6
+ import { ContainerType } from "./ContainerType.js";
7
+ import { Point } from "./Point.js";
8
+ import { Utils } from "./Utils.js";
9
+ import { IThickness } from "./interfaces/IThickness.js";
10
+ import { IState } from "./interfaces/IState.js";
11
+
12
+ /**
13
+ * Decorates a dock container with resizer handles around its base element
14
+ * This enables the container to be resized from all directions
15
+ */
16
+ export class ResizableContainer implements IDockContainer {
17
+
18
+ topLevelElement: HTMLElement;
19
+ dialog: Dialog;
20
+ delegate: IDockContainer;
21
+ dockManager: DockManager;
22
+ containerElement: HTMLElement;
23
+ containerType: ContainerType;
24
+ minimumAllowedChildNodes: number;
25
+ readyToProcessNextResize: boolean;
26
+ dockSpawnResizedEvent: CustomEvent<{}>;
27
+ resizeHandles: ResizeHandle[];
28
+ previousMousePosition: Point;
29
+ private iframeEventHandlers: EventHandler[];
30
+ private disableResize: boolean;
31
+
32
+ constructor(dialog: Dialog, delegate: IDockContainer, topLevelElement: HTMLElement, disableResize: boolean = false) {
33
+ this.dialog = dialog;
34
+ this.disableResize = disableResize;
35
+ this.delegate = delegate;
36
+ this.containerElement = delegate.containerElement;
37
+ this.dockManager = delegate.dockManager;
38
+ this.topLevelElement = topLevelElement;
39
+ this.containerType = delegate.containerType;
40
+ this.topLevelElement.style.left = this.topLevelElement.offsetLeft + 'px';
41
+ this.topLevelElement.style.top = this.topLevelElement.offsetTop + 'px';
42
+ this.minimumAllowedChildNodes = delegate.minimumAllowedChildNodes;
43
+ this._buildResizeHandles();
44
+ this.readyToProcessNextResize = true;
45
+ this.dockSpawnResizedEvent = new CustomEvent("DockSpawnResizedEvent", { composed: true, bubbles: true });
46
+ this.iframeEventHandlers = [];
47
+ }
48
+
49
+ setActiveChild(/*child*/) {
50
+ }
51
+
52
+ _buildResizeHandles() {
53
+ this.resizeHandles = [];
54
+ // this._buildResizeHandle(true, false, true, false); // Dont need the corner resizer near the close button
55
+ if (!this.disableResize) {
56
+ this._buildResizeHandle(false, true, true, false);
57
+ this._buildResizeHandle(true, false, false, true);
58
+ this._buildResizeHandle(false, true, false, true);
59
+
60
+ this._buildResizeHandle(true, false, false, false);
61
+ this._buildResizeHandle(false, true, false, false);
62
+ this._buildResizeHandle(false, false, true, false);
63
+ this._buildResizeHandle(false, false, false, true);
64
+ }
65
+ }
66
+
67
+ _buildResizeHandle(east: boolean, west: boolean, north: boolean, south: boolean) {
68
+ let handle = new ResizeHandle();
69
+ handle.east = east;
70
+ handle.west = west;
71
+ handle.north = north;
72
+ handle.south = south;
73
+
74
+ // Create an invisible div for the handle
75
+ handle.element = document.createElement('div');
76
+ this.topLevelElement.appendChild(handle.element);
77
+
78
+ // Build the class name for the handle
79
+ let verticalClass = '';
80
+ let horizontalClass = '';
81
+ if (north) verticalClass = 'n';
82
+ if (south) verticalClass = 's';
83
+ if (east) horizontalClass = 'e';
84
+ if (west) horizontalClass = 'w';
85
+ let cssClass = 'resize-handle-' + verticalClass + horizontalClass;
86
+ if (verticalClass.length > 0 && horizontalClass.length > 0)
87
+ handle.corner = true;
88
+
89
+ handle.element.classList.add(handle.corner ? 'resize-handle-corner' : 'resize-handle');
90
+ handle.element.classList.add(cssClass);
91
+ this.resizeHandles.push(handle);
92
+
93
+ handle.mouseDownHandler = new EventHandler(handle.element, 'mousedown', (e) => { this.onMouseDown(handle, <MouseEvent>e); });
94
+ handle.touchDownHandler = new EventHandler(handle.element, 'touchstart', (e) => { this.onMouseDown(handle, <TouchEvent>e); });
95
+ }
96
+
97
+ saveState(state: IState) {
98
+ this.delegate.saveState(state);
99
+ }
100
+
101
+ loadState(state: IState) {
102
+ this.delegate.loadState(state);
103
+ }
104
+
105
+ get width(): number {
106
+ return this.delegate.width;
107
+ }
108
+
109
+ get height(): number {
110
+ return this.delegate.height;
111
+ }
112
+
113
+ get name() {
114
+ return this.delegate.name;
115
+ }
116
+ set name(value) {
117
+ if (value)
118
+ this.delegate.name = value;
119
+ }
120
+
121
+ resize(width: number, height: number) {
122
+ this.delegate.resize(width, height);
123
+ this._adjustResizeHandles(width, height);
124
+ document.dispatchEvent(this.dockSpawnResizedEvent);
125
+ }
126
+
127
+ _adjustResizeHandles(width: number, height: number) {
128
+ this.resizeHandles.forEach((handle) => {
129
+ handle.adjustSize(width, height);
130
+ });
131
+ }
132
+
133
+ performLayout(children) {
134
+ this.delegate.performLayout(children, false);
135
+ }
136
+
137
+ destroy() {
138
+ this.removeDecorator();
139
+ this.delegate.destroy();
140
+ }
141
+
142
+ removeDecorator() {
143
+ }
144
+
145
+ onMouseMovedIframe(handle, e: MouseEvent, iframe: HTMLIFrameElement) {
146
+ let posIf = iframe.getBoundingClientRect();
147
+ this.onMouseMoved(handle, e, { x: posIf.x, y: posIf.y });
148
+ }
149
+
150
+ onMouseMoved(handle: ResizeHandle, event: TouchEvent | MouseEvent, iframeOffset?: { x: number, y: number }) {
151
+ let touchOrMouseData: { clientX: number, clientY: number } = null;
152
+ if ((<TouchEvent>event).changedTouches) {
153
+ if ((<TouchEvent>event).changedTouches.length > 1)
154
+ return;
155
+ touchOrMouseData = (<TouchEvent>event).changedTouches[0];
156
+ } else {
157
+ touchOrMouseData = <MouseEvent>event;
158
+ }
159
+
160
+ if (!this.readyToProcessNextResize)
161
+ return;
162
+ this.readyToProcessNextResize = false;
163
+
164
+ if (this.dialog.panel)
165
+ this.dockManager.suspendLayout(this.dialog.panel);
166
+ let currentMousePosition = new Point(touchOrMouseData.clientX, touchOrMouseData.clientY);
167
+ if (iframeOffset)
168
+ currentMousePosition = new Point(touchOrMouseData.clientX + iframeOffset.x, touchOrMouseData.clientY + iframeOffset.y);
169
+ let dx = this.dockManager.checkXBounds(this.topLevelElement, currentMousePosition, this.previousMousePosition, handle.west, handle.east);
170
+ let dy = this.dockManager.checkYBounds(this.topLevelElement, currentMousePosition, this.previousMousePosition, handle.north, handle.south);
171
+ this._performDrag(handle, dx, dy);
172
+ this.previousMousePosition = currentMousePosition;
173
+ this.readyToProcessNextResize = true;
174
+ if (this.dialog.panel)
175
+ this.dockManager.resumeLayout(this.dialog.panel);
176
+
177
+ this.dockManager.notifyOnContainerResized(this);
178
+ }
179
+
180
+ onMouseDown(handle, event: TouchEvent | MouseEvent) {
181
+ let touchOrMouseData: { clientX: number, clientY: number } = null;
182
+ if ((<TouchEvent>event).touches) {
183
+ if ((<TouchEvent>event).touches.length > 1)
184
+ return;
185
+ touchOrMouseData = (<TouchEvent>event).touches[0];
186
+ } else {
187
+ touchOrMouseData = <MouseEvent>event;
188
+ }
189
+
190
+ this.previousMousePosition = new Point(touchOrMouseData.clientX, touchOrMouseData.clientY);
191
+ if (handle.mouseMoveHandler) {
192
+ handle.mouseMoveHandler.cancel();
193
+ delete handle.mouseMoveHandler;
194
+ }
195
+ if (handle.touchMoveHandler) {
196
+ handle.touchMoveHandler.cancel();
197
+ delete handle.touchMoveHandler;
198
+ }
199
+ if (handle.mouseUpHandler) {
200
+ handle.mouseUpHandler.cancel();
201
+ delete handle.mouseUpHandler;
202
+ }
203
+ if (handle.touchUpHandler) {
204
+ handle.touchUpHandler.cancel();
205
+ delete handle.touchUpHandler;
206
+ }
207
+ for (let e of this.iframeEventHandlers) {
208
+ e.cancel();
209
+ }
210
+ this.iframeEventHandlers = [];
211
+
212
+ // Create the mouse event handlers
213
+ handle.mouseMoveHandler = new EventHandler(window, 'mousemove', (e) => { this.onMouseMoved(handle, <MouseEvent>e); });
214
+ handle.touchMoveHandler = new EventHandler(window, 'touchmove', (e) => { this.onMouseMoved(handle, <TouchEvent>e); });
215
+ handle.mouseUpHandler = new EventHandler(window, 'mouseup', (e) => { this.onMouseUp(handle); });
216
+ handle.touchUpHandler = new EventHandler(window, 'touchend', (e) => { this.onMouseUp(handle); });
217
+
218
+ if (this.dockManager.iframes) {
219
+ for (let f of this.dockManager.iframes) {
220
+ let mmi = this.onMouseMovedIframe.bind(this);
221
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'mousemove', (e) => mmi(handle, e, f)));
222
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'mouseup', (e) => this.onMouseUp(handle)));
223
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'touchmove', (e) => mmi(handle, e, f)));
224
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'touchend', (e) => this.onMouseUp(handle)));
225
+ }
226
+ }
227
+
228
+ Utils.disableGlobalTextSelection(this.dockManager.config.dialogRootElement);
229
+ }
230
+
231
+ onMouseUp(handle) {
232
+ handle.mouseMoveHandler.cancel();
233
+ handle.touchMoveHandler.cancel();
234
+ handle.mouseUpHandler.cancel();
235
+ handle.touchUpHandler.cancel();
236
+ delete handle.mouseMoveHandler;
237
+ delete handle.touchMoveHandler;
238
+ delete handle.mouseUpHandler;
239
+ delete handle.touchUpHandler;
240
+ for (let e of this.iframeEventHandlers) {
241
+ e.cancel();
242
+ }
243
+ this.iframeEventHandlers = [];
244
+
245
+ Utils.enableGlobalTextSelection(this.dockManager.config.dialogRootElement);
246
+ }
247
+
248
+ _performDrag(handle, dx: number, dy: number) {
249
+ let bounds: IThickness = {};
250
+ bounds.left = Utils.getPixels(this.topLevelElement.style.left);
251
+ bounds.top = Utils.getPixels(this.topLevelElement.style.top);
252
+ bounds.width = this.topLevelElement.clientWidth;
253
+ bounds.height = this.topLevelElement.clientHeight;
254
+
255
+ if (handle.east) this._resizeEast(dx, bounds);
256
+ if (handle.west) this._resizeWest(dx, bounds);
257
+ if (handle.north) this._resizeNorth(dy, bounds);
258
+ if (handle.south) this._resizeSouth(dy, bounds);
259
+ }
260
+
261
+ _resizeWest(dx: number, bounds: IThickness) {
262
+ this._resizeContainer(dx, 0, -dx, 0, bounds);
263
+ }
264
+
265
+ _resizeEast(dx: number, bounds: IThickness) {
266
+ this._resizeContainer(0, 0, dx, 0, bounds);
267
+ }
268
+
269
+ _resizeNorth(dy: number, bounds: IThickness) {
270
+ this._resizeContainer(0, dy, 0, -dy, bounds);
271
+ }
272
+
273
+ _resizeSouth(dy: number, bounds: IThickness) {
274
+ this._resizeContainer(0, 0, 0, dy, bounds);
275
+ }
276
+
277
+ _resizeContainer(leftDelta: number, topDelta: number, widthDelta: number, heightDelta: number, bounds: IThickness) {
278
+ bounds.left += leftDelta;
279
+ bounds.top += topDelta;
280
+ bounds.width += widthDelta;
281
+ bounds.height += heightDelta;
282
+
283
+ let minWidth = 50; // TODO: Move to external configuration
284
+ let minHeight = 50; // TODO: Move to external configuration
285
+ bounds.width = Math.max(bounds.width, minWidth);
286
+ bounds.height = Math.max(bounds.height, minHeight);
287
+
288
+ this.topLevelElement.style.left = bounds.left + 'px';
289
+ this.topLevelElement.style.top = bounds.top + 'px';
290
+
291
+ this.resize(bounds.width, bounds.height);
292
+ }
293
+ }
@@ -0,0 +1,59 @@
1
+ import { EventHandler } from "./EventHandler.js";
2
+
3
+ export class ResizeHandle {
4
+
5
+ element: HTMLElement;
6
+ handleSize: number;
7
+ cornerSize: number;
8
+ east: boolean;
9
+ west: boolean;
10
+ north: boolean;
11
+ south: boolean;
12
+ corner: boolean;
13
+ mouseDownHandler: EventHandler;
14
+ touchDownHandler: EventHandler;
15
+
16
+ constructor() {
17
+ this.element = undefined;
18
+ this.handleSize = 6; // TODO: Get this from DOM
19
+ this.cornerSize = 12; // TODO: Get this from DOM
20
+ this.east = false;
21
+ this.west = false;
22
+ this.north = false;
23
+ this.south = false;
24
+ this.corner = false;
25
+ }
26
+
27
+ adjustSize(clientWidth: number, clientHeight: number) {
28
+ if (this.corner) {
29
+ if (this.west) this.element.style.left = '0px';
30
+ if (this.east) this.element.style.left = (clientWidth - this.cornerSize) + 'px';
31
+ if (this.north) this.element.style.top = '0px';
32
+ if (this.south) this.element.style.top = (clientHeight - this.cornerSize) + 'px';
33
+ }
34
+ else {
35
+ if (this.west) {
36
+ this.element.style.left = '0px';
37
+ this.element.style.top = this.cornerSize + 'px';
38
+ }
39
+ if (this.east) {
40
+ this.element.style.left = (clientWidth - this.handleSize) + 'px';
41
+ this.element.style.top = this.cornerSize + 'px';
42
+ }
43
+ if (this.north) {
44
+ this.element.style.left = this.cornerSize + 'px';
45
+ this.element.style.top = '0px';
46
+ }
47
+ if (this.south) {
48
+ this.element.style.left = this.cornerSize + 'px';
49
+ this.element.style.top = (clientHeight - this.handleSize) + 'px';
50
+ }
51
+
52
+ if (this.west || this.east) {
53
+ this.element.style.height = (clientHeight - this.cornerSize * 2) + 'px';
54
+ } else {
55
+ this.element.style.width = (clientWidth - this.cornerSize * 2) + 'px';
56
+ }
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,157 @@
1
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
2
+ import { EventHandler } from "./EventHandler.js";
3
+ import { Utils } from "./Utils.js";
4
+ import { IMouseOrTouchEvent } from "./interfaces/IMouseOrTouchEvent.js";
5
+
6
+ export class SplitterBar {
7
+ previousContainer: IDockContainer;
8
+ nextContainer: IDockContainer;
9
+ stackedVertical: boolean;
10
+ barElement: HTMLDivElement;
11
+ pointerDownHandler: EventHandler;
12
+ minPanelSize: number;
13
+ readyToProcessNextDrag: boolean;
14
+ dockSpawnResizedEvent: CustomEvent<{}>;
15
+ previousMouseEvent: { x: number, y: number };
16
+ pointerMovedHandler: EventHandler;
17
+ pointerUpHandler: EventHandler;
18
+
19
+ private iframeEventHandlers: EventHandler[];
20
+
21
+ constructor(previousContainer: IDockContainer, nextContainer: IDockContainer, stackedVertical: boolean) {
22
+ // The panel to the left/top side of the bar, depending on the bar orientation
23
+ this.previousContainer = previousContainer;
24
+ // The panel to the right/bottom side of the bar, depending on the bar orientation
25
+ this.nextContainer = nextContainer;
26
+ this.stackedVertical = stackedVertical;
27
+ this.barElement = document.createElement('div');
28
+ this.barElement.classList.add(stackedVertical ? 'splitbar-horizontal' : 'splitbar-vertical');
29
+ this.pointerDownHandler = new EventHandler(this.barElement, 'pointerdown', this.onPointerDown.bind(this));
30
+ this.minPanelSize = 50; // TODO: Get from container configuration
31
+ this.readyToProcessNextDrag = true;
32
+ this.dockSpawnResizedEvent = new CustomEvent("DockSpawnResizedEvent", { composed: true, bubbles: true });
33
+ this.iframeEventHandlers = [];
34
+ }
35
+
36
+ onPointerDown(e: PointerEvent) {
37
+ this.barElement.setPointerCapture(e.pointerId);
38
+ this._startDragging(e);
39
+ }
40
+
41
+ onPointerUp(e: PointerEvent) {
42
+ this.barElement.releasePointerCapture(e.pointerId);
43
+ this._stopDragging();
44
+ }
45
+
46
+ onPointerMovedIframe(e: IMouseOrTouchEvent, iframe: HTMLIFrameElement) {
47
+ if (e.changedTouches != null) {
48
+ e = e.changedTouches[0];
49
+ }
50
+ let posIf = iframe.getBoundingClientRect();
51
+ this.handleMoveEvent({ x: parseInt("" + e.clientX + posIf.x), y: parseInt("" + e.clientY + posIf.y) });
52
+ }
53
+
54
+ onPointerMoved(e: IMouseOrTouchEvent) {
55
+ if (e.changedTouches != null) {
56
+ e = e.changedTouches[0];
57
+ }
58
+ this.handleMoveEvent({ x: parseInt("" + e.clientX), y: parseInt("" + e.clientY) });
59
+ }
60
+
61
+ handleMoveEvent(pos: { x: number, y: number }) {
62
+ if (!this.readyToProcessNextDrag)
63
+ return;
64
+ this.readyToProcessNextDrag = false;
65
+
66
+ let dockManager = this.previousContainer.dockManager;
67
+ dockManager.suspendLayout(this.previousContainer);
68
+ dockManager.suspendLayout(this.nextContainer);
69
+ let dx = pos.x - this.previousMouseEvent.x;
70
+ let dy = pos.y - this.previousMouseEvent.y;
71
+ this._performDrag(dx, dy);
72
+ this.previousMouseEvent = pos;
73
+ this.readyToProcessNextDrag = true;
74
+ dockManager.resumeLayout(this.previousContainer);
75
+ dockManager.resumeLayout(this.nextContainer);
76
+ }
77
+
78
+ _performDrag(dx: number, dy: number) {
79
+ let previousWidth = this.previousContainer.containerElement.clientWidth;
80
+ let previousHeight = this.previousContainer.containerElement.clientHeight;
81
+ let nextWidth = this.nextContainer.containerElement.clientWidth;
82
+ let nextHeight = this.nextContainer.containerElement.clientHeight;
83
+
84
+ let previousPanelSize = this.stackedVertical ? previousHeight : previousWidth;
85
+ let nextPanelSize = this.stackedVertical ? nextHeight : nextWidth;
86
+ let deltaMovement = this.stackedVertical ? dy : dx;
87
+ let newPreviousPanelSize = previousPanelSize + deltaMovement;
88
+ let newNextPanelSize = nextPanelSize - deltaMovement;
89
+
90
+ if (newPreviousPanelSize < this.minPanelSize || newNextPanelSize < this.minPanelSize) {
91
+ // One of the panels is smaller than it should be.
92
+ // In that case, check if the small panel's size is being increased
93
+ let continueProcessing = (newPreviousPanelSize < this.minPanelSize && newPreviousPanelSize > previousPanelSize) ||
94
+ (newNextPanelSize < this.minPanelSize && newNextPanelSize > nextPanelSize);
95
+
96
+ if (!continueProcessing)
97
+ return;
98
+ }
99
+
100
+ if (this.stackedVertical) {
101
+ this.previousContainer.resize(previousWidth, newPreviousPanelSize);
102
+ this.nextContainer.resize(nextWidth, newNextPanelSize);
103
+ }
104
+ else {
105
+ if (deltaMovement < 0) {
106
+ this.previousContainer.resize(newPreviousPanelSize, previousHeight);
107
+ this.nextContainer.resize(newNextPanelSize, nextHeight);
108
+ } else {
109
+ this.nextContainer.resize(newNextPanelSize, nextHeight);
110
+ this.previousContainer.resize(newPreviousPanelSize, previousHeight);
111
+ this.nextContainer.resize(newNextPanelSize, nextHeight);
112
+ }
113
+ }
114
+
115
+ document.dispatchEvent(this.dockSpawnResizedEvent);
116
+ }
117
+
118
+ _startDragging(e: IMouseOrTouchEvent) {
119
+ Utils.disableGlobalTextSelection(this.previousContainer.dockManager.config.dialogRootElement);
120
+ if (this.pointerMovedHandler) {
121
+ this.pointerMovedHandler.cancel();
122
+ delete this.pointerMovedHandler;
123
+ }
124
+ if (this.pointerUpHandler) {
125
+ this.pointerUpHandler.cancel();
126
+ delete this.pointerUpHandler;
127
+ }
128
+ this.pointerMovedHandler = new EventHandler(window, 'pointermove', this.onPointerMoved.bind(this));
129
+ this.pointerUpHandler = new EventHandler(window, 'pointerup', this.onPointerUp.bind(this));
130
+
131
+ if (this.previousContainer.dockManager.iframes) {
132
+ for (let f of this.previousContainer.dockManager.iframes) {
133
+ let mmi = this.onPointerMovedIframe.bind(this);
134
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'pointermove', (e) => mmi(e, f)));
135
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'pointerup', this.onPointerUp.bind(this)));
136
+ }
137
+ }
138
+
139
+ this.previousMouseEvent = { x: e.clientX, y: e.clientY };
140
+ }
141
+
142
+ _stopDragging() {
143
+ Utils.enableGlobalTextSelection(this.previousContainer.dockManager.config.dialogRootElement);
144
+ if (this.pointerMovedHandler) {
145
+ this.pointerMovedHandler.cancel();
146
+ delete this.pointerMovedHandler;
147
+ }
148
+ if (this.pointerUpHandler) {
149
+ this.pointerUpHandler.cancel();
150
+ delete this.pointerUpHandler;
151
+ }
152
+ for (let e of this.iframeEventHandlers) {
153
+ e.cancel();
154
+ }
155
+ this.iframeEventHandlers = [];
156
+ }
157
+ }
@@ -0,0 +1,95 @@
1
+ import { DockManager } from "./DockManager.js";
2
+ import { SplitterPanel } from "./SplitterPanel.js";
3
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
4
+ import { ContainerType } from "./ContainerType.js";
5
+ import { ISize } from "./interfaces/ISize.js";
6
+ import { IDockContainerWithSize } from "./interfaces/IDockContainerWithSize.js";
7
+ import { IState } from "./interfaces/IState.js";
8
+
9
+ export abstract class SplitterDockContainer implements IDockContainerWithSize {
10
+ name: string;
11
+ dockManager: DockManager;
12
+ minimumAllowedChildNodes: number;
13
+ splitterPanel: SplitterPanel;
14
+ stackedVertical: boolean;
15
+ containerElement: HTMLDivElement;
16
+ _cachedWidth: number;
17
+ _cachedHeight: number;
18
+ state: ISize;
19
+ containerType: ContainerType;
20
+
21
+ constructor(name: string, dockManager: DockManager, childContainers: IDockContainer[], stackedVertical: boolean) {
22
+ // for prototype inheritance purposes only
23
+ if (arguments.length === 0) {
24
+ return;
25
+ }
26
+
27
+ this.name = name;
28
+ this.dockManager = dockManager;
29
+ this.stackedVertical = stackedVertical;
30
+ this.splitterPanel = new SplitterPanel(childContainers, this.stackedVertical);
31
+ this.containerElement = this.splitterPanel.panelElement;
32
+ this.minimumAllowedChildNodes = 2;
33
+ }
34
+
35
+ resize(width: number, height: number) {
36
+ // if (_cachedWidth === _cachedWidth && _cachedHeight === _height) {
37
+ // // No need to resize
38
+ // return;
39
+ // }
40
+ this.splitterPanel.resize(width, height);
41
+ this._cachedWidth = width;
42
+ this._cachedHeight = height;
43
+ }
44
+
45
+ performLayout(childContainers: IDockContainer[], relayoutEvenIfEqual: boolean = false) {
46
+ this.splitterPanel.performLayout(childContainers, relayoutEvenIfEqual);
47
+ }
48
+
49
+ setActiveChild(/*child*/) {
50
+ }
51
+
52
+ destroy() {
53
+ this.splitterPanel.destroy();
54
+ }
55
+
56
+ /**
57
+ * Sets the percentage of space the specified [container] takes in the split panel
58
+ * The percentage is specified in [ratio] and is between 0..1
59
+ */
60
+ setContainerRatio(container: IDockContainer, ratio: number) {
61
+ this.splitterPanel.setContainerRatio(container, ratio);
62
+ this.resize(this.width, this.height);
63
+ }
64
+
65
+ getRatios(): number[] {
66
+ return this.splitterPanel.getRatios();
67
+ }
68
+
69
+ setRatios(ratios: number[]) {
70
+ this.splitterPanel.setRatios(ratios);
71
+ this.resize(this.width, this.height);
72
+ }
73
+
74
+ saveState(state: IState) {
75
+ state.width = this.width;
76
+ state.height = this.height;
77
+ }
78
+
79
+ loadState(state: IState) {
80
+ this.state = { width: state.width, height: state.height };
81
+ // this.resize(state.width, state.height);
82
+ }
83
+
84
+ get width(): number {
85
+ if (this._cachedWidth === undefined)
86
+ this._cachedWidth = this.splitterPanel.panelElement.clientWidth;
87
+ return this._cachedWidth;
88
+ }
89
+
90
+ get height(): number {
91
+ if (this._cachedHeight === undefined)
92
+ this._cachedHeight = this.splitterPanel.panelElement.clientHeight;
93
+ return this._cachedHeight;
94
+ }
95
+ }