@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
@@ -0,0 +1,16 @@
1
+ import { DockModel } from "./DockModel.js";
2
+ import { DockManager } from "./DockManager.js";
3
+ import { DocumentManagerContainer } from "./DocumentManagerContainer.js";
4
+
5
+ export class DockManagerContext {
6
+
7
+ dockManager: DockManager;
8
+ model: DockModel;
9
+ documentManagerView: DocumentManagerContainer;
10
+
11
+ constructor(dockManager : DockManager) {
12
+ this.dockManager = dockManager;
13
+ this.model = new DockModel();
14
+ this.documentManagerView = new DocumentManagerContainer(this.dockManager);
15
+ }
16
+ }
@@ -0,0 +1,12 @@
1
+ import { DockNode } from "./DockNode.js";
2
+ import { Dialog } from "./Dialog.js";
3
+
4
+ export class DockModel {
5
+ rootNode: DockNode;
6
+ documentManagerNode: DockNode;
7
+ dialogs: Dialog[]
8
+
9
+ constructor() {
10
+ this.rootNode = this.documentManagerNode = undefined;
11
+ }
12
+ }
@@ -0,0 +1,81 @@
1
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
2
+
3
+ export class DockNode {
4
+
5
+ parent: DockNode;
6
+ container: IDockContainer;
7
+ children: DockNode[];
8
+
9
+ constructor(container: IDockContainer) {
10
+ /** The dock container represented by this node */
11
+ this.container = container;
12
+ this.children = [];
13
+ }
14
+
15
+ detachFromParent() {
16
+ if (this.parent) {
17
+ this.parent.removeChild(this);
18
+ delete this.parent;
19
+ }
20
+ }
21
+
22
+ removeChild(childNode: DockNode) {
23
+ let index = this.children.indexOf(childNode);
24
+ if (index >= 0)
25
+ this.children.splice(index, 1);
26
+ }
27
+
28
+ addChild(childNode: DockNode) {
29
+ childNode.detachFromParent();
30
+ childNode.parent = this;
31
+ this.children.push(childNode);
32
+ }
33
+
34
+ addChildBefore(referenceNode: DockNode, childNode: DockNode) {
35
+ this._addChildWithDirection(referenceNode, childNode, true);
36
+ }
37
+
38
+ addChildAfter(referenceNode: DockNode, childNode: DockNode) {
39
+ this._addChildWithDirection(referenceNode, childNode, false);
40
+ }
41
+
42
+ _addChildWithDirection(referenceNode: DockNode, childNode: DockNode, before: boolean) {
43
+ // Detach this node from it's parent first
44
+ childNode.detachFromParent();
45
+ childNode.parent = this;
46
+
47
+ let referenceIndex = this.children.indexOf(referenceNode);
48
+ let preList = this.children.slice(0, referenceIndex);
49
+ let postList = this.children.slice(referenceIndex + 1, this.children.length);
50
+
51
+ this.children = preList.slice(0);
52
+ if (before) {
53
+ this.children.push(childNode);
54
+ this.children.push(referenceNode);
55
+ }
56
+ else {
57
+ this.children.push(referenceNode);
58
+ this.children.push(childNode);
59
+ }
60
+ Array.prototype.push.apply(this.children, postList);
61
+ }
62
+
63
+ performLayout(relayoutEvenIfEqual: boolean) {
64
+ let childContainers = this.children.map((childNode) => { return childNode.container; });
65
+ this.container.performLayout(childContainers, relayoutEvenIfEqual);
66
+ }
67
+
68
+ debugDumpTree(indent: number) {
69
+ if (indent === undefined)
70
+ indent = 0;
71
+
72
+ let message = this.container.name;
73
+ for (let i = 0; i < indent; i++)
74
+ message = '\t' + message;
75
+
76
+ let parentType = this.parent === undefined ? 'null' : this.parent.container.containerType;
77
+ console.log('>>' + message + ' [' + parentType + ']');
78
+
79
+ this.children.forEach((childNode) => { childNode.debugDumpTree(indent + 1); });
80
+ }
81
+ }
@@ -0,0 +1,215 @@
1
+ import { Utils } from "./Utils.js";
2
+ import { DockManager } from "./DockManager.js";
3
+ import { DockWheelItem } from "./DockWheelItem.js";
4
+ import { WheelTypes } from "./enums/WheelTypes.js";
5
+ import { Dialog } from "./Dialog.js";
6
+ import { DockNode } from "./DockNode.js";
7
+
8
+ /**
9
+ * Manages the dock overlay buttons that are displayed over the dock manager
10
+ */
11
+ export class DockWheel {
12
+ dockManager: DockManager;
13
+ elementMainWheel: HTMLDivElement;
14
+ elementSideWheel: HTMLDivElement;
15
+ wheelItems: { [index in WheelTypes]?: DockWheelItem; };
16
+ elementPanelPreview: HTMLDivElement;
17
+ activeDialog: Dialog;
18
+ _activeNode?: DockNode;
19
+ _visible: boolean;
20
+
21
+ constructor(dockManager: DockManager) {
22
+ this.dockManager = dockManager;
23
+ this.elementMainWheel = document.createElement('div'); // Contains the main wheel's 5 dock buttons
24
+ this.elementSideWheel = document.createElement('div'); // Contains the 4 buttons on the side
25
+ this.wheelItems = {};
26
+ for (let wheelType in WheelTypes) {
27
+ this.wheelItems[wheelType] = new DockWheelItem(this, <WheelTypes>wheelType);
28
+ if (wheelType.substr(-2, 2) === '-s')
29
+ // Side button
30
+ this.elementSideWheel.appendChild(this.wheelItems[wheelType].element);
31
+ else
32
+ // Main dock wheel button
33
+ this.elementMainWheel.appendChild(this.wheelItems[wheelType].element);
34
+ };
35
+
36
+ let zIndex = 9000000;
37
+ this.elementMainWheel.classList.add('dock-wheel-base');
38
+ this.elementSideWheel.classList.add('dock-wheel-base');
39
+ this.elementMainWheel.style.zIndex = String(zIndex + 1);
40
+ this.elementSideWheel.style.zIndex = String(zIndex);
41
+ this.elementPanelPreview = document.createElement('div');
42
+ this.elementPanelPreview.classList.add('dock-wheel-panel-preview');
43
+ this.elementPanelPreview.style.zIndex = String(zIndex - 1);
44
+ this.activeDialog = undefined; // The dialog being dragged, when the wheel is visible
45
+ this._activeNode = undefined;
46
+ this._visible = false;
47
+ }
48
+
49
+ /** The node over which the dock wheel is being displayed on */
50
+ get activeNode(): DockNode {
51
+ return this._activeNode;
52
+ }
53
+ set activeNode(value: DockNode) {
54
+ let previousValue = this._activeNode;
55
+ this._activeNode = value;
56
+
57
+ if (previousValue !== this._activeNode) {
58
+ // The active node has been changed.
59
+ // Reattach the wheel to the new node's element and show it again
60
+ if (this._visible)
61
+ this.showWheel();
62
+ }
63
+ }
64
+
65
+ showWheel() {
66
+ this._visible = true;
67
+ if (!this.activeNode) {
68
+ // No active node selected. make sure the wheel is invisible
69
+ Utils.removeNode(this.elementMainWheel);
70
+ Utils.removeNode(this.elementSideWheel);
71
+ return;
72
+ }
73
+ let element = this.activeNode.container.containerElement;
74
+ let containerWidth = element.clientWidth;
75
+ let containerHeight = element.clientHeight;
76
+ let baseX = Math.floor(containerWidth / 2); // + element.offsetLeft;
77
+ let baseY = Math.floor(containerHeight / 2); // + element.offsetTop;
78
+ let bcElement = element.getBoundingClientRect();
79
+ let bcdockManagerElement = this.dockManager.element.getBoundingClientRect()
80
+ this.elementMainWheel.style.left = (bcElement.left - bcdockManagerElement.left + baseX) + 'px';
81
+ this.elementMainWheel.style.top = (bcElement.top - bcdockManagerElement.top + baseY) + 'px';
82
+
83
+ // The positioning of the main dock wheel buttons is done automatically through CSS
84
+ // Dynamically calculate the positions of the buttons on the extreme sides of the dock manager
85
+ let sideMargin = 20;
86
+ let dockManagerWidth = this.dockManager.element.clientWidth;
87
+ let dockManagerHeight = this.dockManager.element.clientHeight;
88
+
89
+ Utils.removeNode(this.elementMainWheel);
90
+ Utils.removeNode(this.elementSideWheel);
91
+ this.dockManager.element.appendChild(this.elementMainWheel);
92
+ this.dockManager.element.appendChild(this.elementSideWheel);
93
+
94
+ this._setWheelButtonPosition(WheelTypes["left-s"], sideMargin, -dockManagerHeight / 2);
95
+ this._setWheelButtonPosition(WheelTypes["right-s"], dockManagerWidth - sideMargin * 2, -dockManagerHeight / 2);
96
+ this._setWheelButtonPosition(WheelTypes["top-s"], dockManagerWidth / 2, -dockManagerHeight + sideMargin);
97
+ this._setWheelButtonPosition(WheelTypes["down-s"], dockManagerWidth / 2, -sideMargin);
98
+ }
99
+
100
+ _setWheelButtonPosition(wheelId: WheelTypes, left: number, top: number) {
101
+ let item = this.wheelItems[wheelId];
102
+ let itemHalfWidth = item.element.clientWidth / 2;
103
+ let itemHalfHeight = item.element.clientHeight / 2;
104
+
105
+ let x = Math.floor(left - itemHalfWidth);
106
+ let y = Math.floor(top - itemHalfHeight);
107
+ // item.element.style.left = '${x}px';
108
+ // item.element.style.top = '${y}px';
109
+ item.element.style.marginLeft = x + 'px';
110
+ item.element.style.marginTop = y + 'px';
111
+ }
112
+
113
+ hideWheel() {
114
+ this._visible = false;
115
+ this.activeNode = undefined;
116
+ Utils.removeNode(this.elementMainWheel);
117
+ Utils.removeNode(this.elementSideWheel);
118
+ Utils.removeNode(this.elementPanelPreview);
119
+
120
+ // deactivate all wheels
121
+ for (let wheelType in this.wheelItems)
122
+ this.wheelItems[wheelType].active = false;
123
+ }
124
+
125
+ onMouseOver(wheelItem: DockWheelItem) {
126
+ if (!this.activeDialog)
127
+ return;
128
+
129
+ // Display the preview panel to show where the panel would be docked
130
+ let rootNode = this.dockManager.context.model.rootNode;
131
+ let bounds;
132
+ if (wheelItem.id === WheelTypes.top) {
133
+ bounds = this.dockManager.layoutEngine.getDockBounds(this.activeNode, this.activeDialog.panel, 'vertical', true);
134
+ } else if (wheelItem.id === WheelTypes.down) {
135
+ bounds = this.dockManager.layoutEngine.getDockBounds(this.activeNode, this.activeDialog.panel, 'vertical', false);
136
+ } else if (wheelItem.id === WheelTypes.left) {
137
+ bounds = this.dockManager.layoutEngine.getDockBounds(this.activeNode, this.activeDialog.panel, 'horizontal', true);
138
+ } else if (wheelItem.id === WheelTypes.right) {
139
+ bounds = this.dockManager.layoutEngine.getDockBounds(this.activeNode, this.activeDialog.panel, 'horizontal', false);
140
+ } else if (wheelItem.id === WheelTypes.fill) {
141
+ bounds = this.dockManager.layoutEngine.getDockBounds(this.activeNode, this.activeDialog.panel, 'fill', false);
142
+ } else if (wheelItem.id === WheelTypes["top-s"]) {
143
+ bounds = this.dockManager.layoutEngine.getDockBounds(rootNode, this.activeDialog.panel, 'vertical', true);
144
+ } else if (wheelItem.id === WheelTypes["down-s"]) {
145
+ bounds = this.dockManager.layoutEngine.getDockBounds(rootNode, this.activeDialog.panel, 'vertical', false);
146
+ } else if (wheelItem.id === WheelTypes["left-s"]) {
147
+ bounds = this.dockManager.layoutEngine.getDockBounds(rootNode, this.activeDialog.panel, 'horizontal', true);
148
+ } else if (wheelItem.id === WheelTypes["right-s"]) {
149
+ bounds = this.dockManager.layoutEngine.getDockBounds(rootNode, this.activeDialog.panel, 'horizontal', false);
150
+ }
151
+
152
+ if (bounds) {
153
+ this.dockManager.element.appendChild(this.elementPanelPreview);
154
+ this.elementPanelPreview.style.left = Math.round(bounds.x) + 'px';
155
+ this.elementPanelPreview.style.top = Math.round(bounds.y) + 'px';
156
+ this.elementPanelPreview.style.width = Math.round(bounds.width) + 'px';
157
+ this.elementPanelPreview.style.height = Math.round(bounds.height) + 'px';
158
+ }
159
+ }
160
+
161
+ onMouseOut() {
162
+ Utils.removeNode(this.elementPanelPreview);
163
+ }
164
+
165
+ /**
166
+ * Called if the dialog is dropped in a dock panel.
167
+ * The dialog might not necessarily be dropped in one of the dock wheel buttons,
168
+ * in which case the request will be ignored
169
+ */
170
+ onDialogDropped(dialog: Dialog) {
171
+ // Check if the dialog was dropped in one of the wheel items
172
+ let wheelItem = this._getActiveWheelItem();
173
+ if (wheelItem)
174
+ this._handleDockRequest(wheelItem, dialog);
175
+ }
176
+
177
+ /**
178
+ * Returns the wheel item which has the mouse cursor on top of it
179
+ */
180
+ _getActiveWheelItem(): DockWheelItem {
181
+ for (let wheelType in this.wheelItems) {
182
+ let wheelItem = this.wheelItems[wheelType];
183
+ if (wheelItem.active)
184
+ return wheelItem;
185
+ }
186
+ return this.wheelItems[WheelTypes.fill];
187
+ }
188
+
189
+ _handleDockRequest(wheelItem: DockWheelItem, dialog: Dialog) {
190
+ wheelItem.active = false;
191
+ wheelItem.element.classList.remove(wheelItem.hoverIconClass);
192
+
193
+ if (!this.activeNode)
194
+ return;
195
+ if (wheelItem.id === WheelTypes.left) {
196
+ this.dockManager.dockDialogLeft(this.activeNode, dialog);
197
+ } else if (wheelItem.id === WheelTypes.right) {
198
+ this.dockManager.dockDialogRight(this.activeNode, dialog);
199
+ } else if (wheelItem.id === WheelTypes.top) {
200
+ this.dockManager.dockDialogUp(this.activeNode, dialog);
201
+ } else if (wheelItem.id === WheelTypes.down) {
202
+ this.dockManager.dockDialogDown(this.activeNode, dialog);
203
+ } else if (wheelItem.id === WheelTypes.fill) {
204
+ this.dockManager.dockDialogFill(this.activeNode, dialog);
205
+ } else if (wheelItem.id === WheelTypes["left-s"]) {
206
+ this.dockManager.dockDialogLeft(this.dockManager.context.model.rootNode, dialog);
207
+ } else if (wheelItem.id === WheelTypes["right-s"]) {
208
+ this.dockManager.dockDialogRight(this.dockManager.context.model.rootNode, dialog);
209
+ } else if (wheelItem.id === WheelTypes["top-s"]) {
210
+ this.dockManager.dockDialogUp(this.dockManager.context.model.rootNode, dialog);
211
+ } else if (wheelItem.id === WheelTypes["down-s"]) {
212
+ this.dockManager.dockDialogDown(this.dockManager.context.model.rootNode, dialog);
213
+ }
214
+ }
215
+ }
@@ -0,0 +1,41 @@
1
+ import { EventHandler } from "./EventHandler.js";
2
+ import { DockWheel } from "./DockWheel.js";
3
+ import { WheelTypes } from "./enums/WheelTypes.js";
4
+
5
+ export class DockWheelItem {
6
+
7
+ wheel: DockWheel;
8
+ id: WheelTypes;
9
+ element: HTMLDivElement;
10
+ hoverIconClass: string;
11
+ mouseOverHandler: EventHandler;
12
+ mouseOutHandler: EventHandler;
13
+ active: boolean;
14
+
15
+ constructor(wheel: DockWheel, id: WheelTypes) {
16
+ this.wheel = wheel;
17
+ this.id = id;
18
+ let wheelType = id.replace('-s', '');
19
+ this.element = document.createElement('div');
20
+ this.element.classList.add('dock-wheel-item');
21
+ this.element.classList.add('disable-selection');
22
+ this.element.classList.add('dock-wheel-' + wheelType);
23
+ this.element.classList.add('dock-wheel-' + wheelType + '-icon');
24
+ this.hoverIconClass = 'dock-wheel-' + wheelType + '-icon-hover';
25
+ this.mouseOverHandler = new EventHandler(this.element, 'pointerover', this.onMouseMoved.bind(this));
26
+ this.mouseOutHandler = new EventHandler(this.element, 'pointerout', this.onMouseOut.bind(this));
27
+ this.active = false; // Becomes active when the mouse is hovered over it
28
+ }
29
+
30
+ onMouseMoved() {
31
+ this.active = true;
32
+ this.element.classList.add(this.hoverIconClass);
33
+ this.wheel.onMouseOver(this);
34
+ }
35
+
36
+ onMouseOut() {
37
+ this.active = false;
38
+ this.element.classList.remove(this.hoverIconClass);
39
+ this.wheel.onMouseOut();
40
+ }
41
+ }
@@ -0,0 +1,39 @@
1
+ import { FillDockContainer } from "./FillDockContainer.js";
2
+ import { TabHost } from "./TabHost.js";
3
+ import { DocumentTabPage } from "./DocumentTabPage.js";
4
+ import { DockManager } from "./DockManager.js";
5
+ import { TabHostDirection } from "./enums/TabHostDirection.js";
6
+ import { IState } from "./interfaces/IState.js";
7
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
8
+
9
+ /**
10
+ * The document manager is then central area of the dock layout hierarchy.
11
+ * This is where more important panels are placed (e.g. the text editor in an IDE,
12
+ * 3D view in a modelling package etc
13
+ */
14
+
15
+ export class DocumentManagerContainer extends FillDockContainer {
16
+
17
+ constructor(dockManager: DockManager) {
18
+ super(dockManager, TabHostDirection.TOP);
19
+
20
+ this.minimumAllowedChildNodes = 0;
21
+ this.element.classList.add('document-manager');
22
+ this.tabHost.createTabPage = this._createDocumentTabPage;
23
+ this.tabHost.displayCloseButton = true;
24
+ }
25
+
26
+ private _createDocumentTabPage(tabHost: TabHost, container: IDockContainer) {
27
+ return new DocumentTabPage(tabHost, container);
28
+ }
29
+
30
+ saveState(state: IState) {
31
+ super.saveState(state);
32
+ state.documentManager = true;
33
+ }
34
+
35
+ /** Returns the selected document tab */
36
+ selectedTab() {
37
+ return this.tabHost.activeTab;
38
+ }
39
+ }
@@ -0,0 +1,35 @@
1
+ import { TabHost } from "./TabHost.js";
2
+ import { TabPage } from "./TabPage.js";
3
+ import { Utils } from "./Utils.js";
4
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
5
+ import { PanelContainer } from "./PanelContainer.js";
6
+
7
+ /**
8
+ * Specialized tab page that doesn't display the panel's frame when docked in a tab page
9
+ */
10
+ export class DocumentTabPage extends TabPage {
11
+
12
+ constructor(host: TabHost, container: IDockContainer) {
13
+ super(host, container);
14
+
15
+ // If the container is a panel, extract the content element and set it as the tab's content
16
+ if (this.container.containerType === 'panel') {
17
+ this.panel = container as PanelContainer;
18
+ this.containerElement = this.panel.elementContentWrapper;
19
+
20
+ // detach the container element from the panel's frame.
21
+ // It will be reattached when this tab page is destroyed
22
+ // This enables the panel's frame (title bar etc) to be hidden
23
+ // inside the tab page
24
+ Utils.removeNode(this.containerElement);
25
+ }
26
+ }
27
+
28
+ destroy() {
29
+ super.destroy();
30
+
31
+ // Restore the panel content element back into the panel frame
32
+ //Utils.removeNode(this.containerElement);
33
+ this.panel.elementContentHost.appendChild(this.containerElement);
34
+ }
35
+ }
@@ -0,0 +1,177 @@
1
+ import { Dialog } from "./Dialog.js";
2
+ import { DockManager } from "./DockManager.js";
3
+ import { EventHandler } from "./EventHandler.js";
4
+ import { Point } from "./Point.js";
5
+ import { Utils } from "./Utils.js";
6
+ import { IDockContainer } from "./interfaces/IDockContainer.js";
7
+ import { ContainerType } from "./ContainerType.js";
8
+ import { IState } from "./interfaces/IState.js";
9
+ import { PanelContainer } from "./PanelContainer.js";
10
+
11
+ export class DraggableContainer implements IDockContainer {
12
+
13
+ dialog: Dialog;
14
+ delegate: PanelContainer;
15
+ containerElement: HTMLElement;
16
+ dockManager: DockManager;
17
+ topLevelElement: HTMLElement;
18
+ containerType: ContainerType;
19
+ mouseDownHandler: EventHandler;
20
+ touchDownHandler: EventHandler;
21
+ minimumAllowedChildNodes: number;
22
+ previousMousePosition: { x: any; y: any; };
23
+ mouseMoveHandler: EventHandler;
24
+ mouseUpHandler: EventHandler;
25
+ private iframeEventHandlers: EventHandler[];
26
+
27
+ constructor(dialog: Dialog, delegate: PanelContainer, topLevelElement: HTMLElement, dragHandle: HTMLElement) {
28
+ this.dialog = dialog;
29
+ this.delegate = delegate;
30
+ this.containerElement = delegate.containerElement;
31
+ this.dockManager = delegate.dockManager;
32
+ this.topLevelElement = topLevelElement;
33
+ this.containerType = delegate.containerType;
34
+ this.mouseDownHandler = new EventHandler(dragHandle, 'mousedown', this.onMouseDown.bind(this));
35
+ this.touchDownHandler = new EventHandler(dragHandle, 'touchstart', this.onMouseDown.bind(this));
36
+ this.topLevelElement.style.left = topLevelElement.offsetLeft + 'px';
37
+ this.topLevelElement.style.top = topLevelElement.offsetTop + 'px';
38
+ this.minimumAllowedChildNodes = delegate.minimumAllowedChildNodes;
39
+ this.iframeEventHandlers = [];
40
+ }
41
+
42
+ destroy() {
43
+ this.removeDecorator();
44
+ this.delegate.destroy();
45
+ }
46
+
47
+ saveState(state: IState) {
48
+ this.delegate.saveState(state);
49
+ }
50
+
51
+ loadState(state: IState) {
52
+ this.delegate.loadState(state);
53
+ }
54
+
55
+ setActiveChild(/*child*/) {
56
+ }
57
+
58
+ get width(): number {
59
+ return this.delegate.width;
60
+ }
61
+
62
+ get height(): number {
63
+ return this.delegate.height;
64
+ }
65
+
66
+ get name() {
67
+ return this.delegate.name;
68
+ }
69
+ set name(value) {
70
+ if (value)
71
+ this.delegate.name = value;
72
+ }
73
+
74
+ resize(width: number, height: number) {
75
+ this.delegate.resize(width, height);
76
+ }
77
+
78
+ performLayout(children: IDockContainer[]) {
79
+ this.delegate.performLayout(children, false);
80
+ }
81
+
82
+ removeDecorator() {
83
+ if (this.mouseDownHandler) {
84
+ this.mouseDownHandler.cancel();
85
+ delete this.mouseDownHandler;
86
+ }
87
+ if (this.touchDownHandler) {
88
+ this.touchDownHandler.cancel();
89
+ delete this.touchDownHandler;
90
+ }
91
+ }
92
+
93
+ onMouseDown(event: PointerEvent) {
94
+ if (event.button == 2)
95
+ return;
96
+ if (event.preventDefault)
97
+ event.preventDefault();
98
+
99
+ this._startDragging(event);
100
+ this.previousMousePosition = { x: event.clientX, y: event.clientY };
101
+ if (this.mouseMoveHandler) {
102
+ this.mouseMoveHandler.cancel();
103
+ delete this.mouseMoveHandler;
104
+ }
105
+ if (this.mouseUpHandler) {
106
+ this.mouseUpHandler.cancel();
107
+ delete this.mouseUpHandler;
108
+ }
109
+
110
+ this.mouseMoveHandler = new EventHandler(window, 'pointermove', this.onMouseMove.bind(this));
111
+ this.mouseUpHandler = new EventHandler(window, 'pointerup', this.onMouseUp.bind(this));
112
+
113
+ if (this.dockManager.iframes) {
114
+ for (let f of this.dockManager.iframes) {
115
+ let mmi = this.onMouseMovedIframe.bind(this);
116
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'pointermove', (e) => mmi(e, f)));
117
+ this.iframeEventHandlers.push(new EventHandler(f.contentWindow, 'pointerup', this.onMouseUp.bind(this)));
118
+ }
119
+ }
120
+ }
121
+
122
+ onMouseUp(event) {
123
+ this._stopDragging(event);
124
+ this.mouseMoveHandler.cancel();
125
+ delete this.mouseMoveHandler;
126
+ this.mouseUpHandler.cancel();
127
+ delete this.mouseUpHandler;
128
+ for (let e of this.iframeEventHandlers) {
129
+ e.cancel();
130
+ }
131
+ this.iframeEventHandlers = [];
132
+ }
133
+
134
+ _startDragging(event: { clientX: number, clientY: number }) {
135
+ this.containerElement.classList.add("draggable-dragging-active");
136
+ this.delegate.elementContentContainer.classList.add("draggable-dragging-active");
137
+ if (this.dialog.eventListener)
138
+ this.dialog.eventListener._onDialogDragStarted(this.dialog, event);
139
+ Utils.disableGlobalTextSelection(this.dockManager.config.dialogRootElement);
140
+ }
141
+
142
+ _stopDragging(event) {
143
+ this.containerElement.classList.remove("draggable-dragging-active");
144
+ this.delegate.elementContentContainer.classList.remove("draggable-dragging-active");
145
+ if (this.dialog.eventListener)
146
+ this.dialog.eventListener._onDialogDragEnded(this.dialog, event);
147
+ Utils.enableGlobalTextSelection(this.dockManager.config.dialogRootElement);
148
+ }
149
+
150
+ onMouseMovedIframe(e: PointerEvent, iframe: HTMLIFrameElement) {
151
+ let posIf = iframe.getBoundingClientRect();
152
+ this.onMouseMove(e, { x: posIf.x, y: posIf.y });
153
+ }
154
+
155
+ onMouseMove(event: PointerEvent, iframeOffset?: { x: number, y: number }) {
156
+ if (event.preventDefault)
157
+ event.preventDefault();
158
+
159
+ let currentMousePosition = new Point(event.clientX, event.clientY);
160
+ if (iframeOffset)
161
+ currentMousePosition = new Point(event.clientX + iframeOffset.x, event.clientY + iframeOffset.y);
162
+
163
+ let dx = this.dockManager.checkXBounds(this.topLevelElement, currentMousePosition, this.previousMousePosition, false, false);
164
+ let dy = this.dockManager.checkYBounds(this.topLevelElement, currentMousePosition, this.previousMousePosition, false, false);
165
+ this._performDrag(dx, dy);
166
+ this.previousMousePosition = currentMousePosition;
167
+ }
168
+
169
+ _performDrag(dx: number, dy: number) {
170
+ let left = dx + Utils.getPixels(this.topLevelElement.style.left);
171
+ let top = dy + Utils.getPixels(this.topLevelElement.style.top);
172
+ this.topLevelElement.style.left = left + 'px';
173
+ this.topLevelElement.style.top = top + 'px';
174
+
175
+ this.dialog.panel.setDialogPosition(left, top);
176
+ }
177
+ }
@@ -0,0 +1,17 @@
1
+ export class EventHandler {
2
+ target: EventListenerOrEventListenerObject;
3
+ eventName: string;
4
+ source: Element | Window;
5
+
6
+ constructor(source: Element | Window, eventName: string, target: EventListenerOrEventListenerObject, useCapture?: boolean | AddEventListenerOptions) {
7
+ this.target = target;
8
+ this.eventName = eventName;
9
+ this.source = source;
10
+
11
+ this.source.addEventListener(eventName, this.target, useCapture);
12
+ }
13
+
14
+ cancel() {
15
+ this.source.removeEventListener(this.eventName, this.target);
16
+ }
17
+ }