@datagrok-libraries/dock-spawn-dg 0.0.2 → 0.1.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 (263) hide show
  1. package/CHANGELOG.md +0 -354
  2. package/README.md +0 -3
  3. package/index.d.ts +33 -0
  4. package/index.d.ts.map +1 -0
  5. package/index.js +32 -0
  6. package/package.json +10 -17
  7. package/src/BrowserDialogHelper.d.ts.map +1 -0
  8. package/{lib → src}/BrowserDialogHelper.js +18 -12
  9. package/src/BrowserDialogHelper.ts +48 -47
  10. package/src/ContainerType.d.ts.map +1 -0
  11. package/src/ContainerType.ts +1 -1
  12. package/{lib → src}/Dialog.d.ts +7 -7
  13. package/src/Dialog.d.ts.map +1 -0
  14. package/{lib → src}/Dialog.js +46 -58
  15. package/src/Dialog.ts +253 -250
  16. package/src/DockConfig.d.ts.map +1 -0
  17. package/{lib → src}/DockConfig.js +0 -5
  18. package/src/DockConfig.ts +1 -1
  19. package/{lib → src}/DockGraphDeserializer.d.ts +6 -6
  20. package/src/DockGraphDeserializer.d.ts.map +1 -0
  21. package/src/DockGraphDeserializer.js +133 -0
  22. package/src/DockGraphDeserializer.ts +113 -108
  23. package/src/DockGraphSerializer.d.ts +14 -0
  24. package/src/DockGraphSerializer.d.ts.map +1 -0
  25. package/{lib → src}/DockGraphSerializer.js +11 -11
  26. package/src/DockGraphSerializer.ts +48 -47
  27. package/{lib → src}/DockLayoutEngine.d.ts +12 -12
  28. package/src/DockLayoutEngine.d.ts.map +1 -0
  29. package/{lib → src}/DockLayoutEngine.js +49 -53
  30. package/src/DockLayoutEngine.ts +351 -346
  31. package/{lib → src}/DockManager.d.ts +34 -34
  32. package/src/DockManager.d.ts.map +1 -0
  33. package/{lib → src}/DockManager.js +168 -151
  34. package/src/DockManager.ts +860 -834
  35. package/{lib → src}/DockManagerContext.d.ts +3 -3
  36. package/src/DockManagerContext.d.ts.map +1 -0
  37. package/{lib → src}/DockManagerContext.js +2 -5
  38. package/src/DockManagerContext.ts +5 -5
  39. package/{lib → src}/DockModel.d.ts +2 -2
  40. package/src/DockModel.d.ts.map +1 -0
  41. package/{lib → src}/DockModel.js +0 -3
  42. package/src/DockModel.ts +2 -2
  43. package/{lib → src}/DockNode.d.ts +1 -1
  44. package/src/DockNode.d.ts.map +1 -0
  45. package/{lib → src}/DockNode.js +0 -3
  46. package/src/DockNode.ts +2 -2
  47. package/{lib → src}/DockWheel.d.ts +5 -5
  48. package/src/DockWheel.d.ts.map +1 -0
  49. package/{lib → src}/DockWheel.js +3 -11
  50. package/src/DockWheel.ts +6 -6
  51. package/{lib → src}/DockWheelItem.d.ts +3 -3
  52. package/src/DockWheelItem.d.ts.map +1 -0
  53. package/{lib → src}/DockWheelItem.js +1 -8
  54. package/src/DockWheelItem.ts +4 -4
  55. package/{lib → src}/DocumentManagerContainer.d.ts +4 -4
  56. package/src/DocumentManagerContainer.d.ts.map +1 -0
  57. package/{lib → src}/DocumentManagerContainer.js +3 -3
  58. package/src/DocumentManagerContainer.ts +9 -9
  59. package/{lib → src}/DocumentTabPage.d.ts +3 -3
  60. package/src/DocumentTabPage.d.ts.map +1 -0
  61. package/{lib → src}/DocumentTabPage.js +2 -2
  62. package/src/DocumentTabPage.ts +6 -6
  63. package/{lib → src}/DraggableContainer.d.ts +7 -7
  64. package/src/DraggableContainer.d.ts.map +1 -0
  65. package/{lib → src}/DraggableContainer.js +3 -16
  66. package/src/DraggableContainer.ts +10 -10
  67. package/src/EventHandler.d.ts.map +1 -0
  68. package/{lib → src}/EventHandler.js +0 -3
  69. package/src/EventHandler.ts +1 -1
  70. package/{lib → src}/FillDockContainer.d.ts +8 -8
  71. package/src/FillDockContainer.d.ts.map +1 -0
  72. package/{lib → src}/FillDockContainer.js +4 -14
  73. package/src/FillDockContainer.ts +10 -10
  74. package/src/HorizontalDockContainer.d.ts +7 -0
  75. package/src/HorizontalDockContainer.d.ts.map +1 -0
  76. package/{lib → src}/HorizontalDockContainer.js +3 -3
  77. package/src/HorizontalDockContainer.ts +6 -6
  78. package/{lib → src}/PanelContainer.d.ts +21 -20
  79. package/src/PanelContainer.d.ts.map +1 -0
  80. package/{lib → src}/PanelContainer.js +144 -148
  81. package/src/PanelContainer.ts +590 -577
  82. package/src/Point.d.ts.map +1 -0
  83. package/{lib → src}/Point.js +0 -2
  84. package/{lib → src}/ResizableContainer.d.ts +8 -8
  85. package/src/ResizableContainer.d.ts.map +1 -0
  86. package/{lib → src}/ResizableContainer.js +4 -17
  87. package/src/ResizableContainer.ts +11 -11
  88. package/{lib → src}/ResizeHandle.d.ts +1 -1
  89. package/src/ResizeHandle.d.ts.map +1 -0
  90. package/{lib → src}/ResizeHandle.js +0 -10
  91. package/src/ResizeHandle.ts +2 -2
  92. package/{lib → src}/SplitterBar.d.ts +3 -3
  93. package/src/SplitterBar.d.ts.map +1 -0
  94. package/{lib → src}/SplitterBar.js +2 -14
  95. package/src/SplitterBar.ts +5 -5
  96. package/{lib → src}/SplitterDockContainer.d.ts +7 -7
  97. package/src/SplitterDockContainer.d.ts.map +1 -0
  98. package/{lib → src}/SplitterDockContainer.js +1 -11
  99. package/src/SplitterDockContainer.ts +8 -8
  100. package/{lib → src}/SplitterPanel.d.ts +2 -2
  101. package/src/SplitterPanel.d.ts.map +1 -0
  102. package/{lib → src}/SplitterPanel.js +2 -6
  103. package/src/SplitterPanel.ts +4 -4
  104. package/{lib → src}/TabHandle.d.ts +5 -5
  105. package/src/TabHandle.d.ts.map +1 -0
  106. package/{lib → src}/TabHandle.js +81 -95
  107. package/src/TabHandle.ts +314 -311
  108. package/{lib → src}/TabHost.d.ts +6 -6
  109. package/src/TabHost.d.ts.map +1 -0
  110. package/{lib → src}/TabHost.js +4 -19
  111. package/src/TabHost.ts +9 -9
  112. package/{lib → src}/TabPage.d.ts +4 -4
  113. package/src/TabPage.d.ts.map +1 -0
  114. package/{lib → src}/TabPage.js +3 -10
  115. package/src/TabPage.ts +6 -6
  116. package/{lib → src}/UndockInitiator.d.ts +4 -4
  117. package/src/UndockInitiator.d.ts.map +1 -0
  118. package/{lib → src}/UndockInitiator.js +2 -14
  119. package/src/UndockInitiator.ts +7 -7
  120. package/src/Utils.d.ts.map +1 -0
  121. package/{lib → src}/Utils.js +1 -1
  122. package/src/Utils.ts +1 -1
  123. package/src/VerticalDockContainer.d.ts +7 -0
  124. package/src/VerticalDockContainer.d.ts.map +1 -0
  125. package/{lib → src}/VerticalDockContainer.js +3 -3
  126. package/src/VerticalDockContainer.ts +7 -7
  127. package/src/enums/PanelType.d.ts.map +1 -0
  128. package/src/enums/PanelType.ts +1 -1
  129. package/src/enums/TabHostDirection.d.ts.map +1 -0
  130. package/src/enums/TabHostDirection.ts +1 -1
  131. package/src/enums/WheelTypes.d.ts.map +1 -0
  132. package/src/enums/WheelTypes.ts +1 -1
  133. package/src/i18n/Defaults.d.ts.map +1 -0
  134. package/src/i18n/Defaults.ts +2 -2
  135. package/{lib → src}/i18n/Localizer.d.ts +1 -1
  136. package/src/i18n/Localizer.d.ts.map +1 -0
  137. package/{lib → src}/i18n/Localizer.js +3 -3
  138. package/src/i18n/Localizer.ts +2 -2
  139. package/src/index.d.ts.map +1 -0
  140. package/{lib → src}/interfaces/IDockContainer.d.ts +4 -4
  141. package/src/interfaces/IDockContainer.d.ts.map +1 -0
  142. package/src/interfaces/IDockContainer.ts +7 -7
  143. package/src/interfaces/IDockContainerWithSize.d.ts +6 -0
  144. package/src/interfaces/IDockContainerWithSize.d.ts.map +1 -0
  145. package/src/interfaces/IDockContainerWithSize.ts +3 -3
  146. package/{lib → src}/interfaces/ILayoutEventListener.d.ts +6 -6
  147. package/src/interfaces/ILayoutEventListener.d.ts.map +1 -0
  148. package/src/interfaces/ILayoutEventListener.ts +7 -7
  149. package/src/interfaces/IMouseOrTouchEvent.d.ts.map +1 -0
  150. package/src/interfaces/IMouseOrTouchEvent.ts +1 -1
  151. package/src/interfaces/INodeInfo.d.ts +8 -0
  152. package/src/interfaces/INodeInfo.d.ts.map +1 -0
  153. package/src/interfaces/INodeInfo.ts +2 -2
  154. package/src/interfaces/IPanelInfo.d.ts +10 -0
  155. package/src/interfaces/IPanelInfo.d.ts.map +1 -0
  156. package/src/interfaces/IPanelInfo.ts +3 -3
  157. package/src/interfaces/IRectangle.d.ts.map +1 -0
  158. package/src/interfaces/IRectangle.ts +1 -1
  159. package/src/interfaces/ISize.d.ts.map +1 -0
  160. package/{lib → src}/interfaces/IState.d.ts +1 -0
  161. package/src/interfaces/IState.d.ts.map +1 -0
  162. package/src/interfaces/IState.ts +1 -0
  163. package/src/interfaces/IThickness.d.ts.map +1 -0
  164. package/src/interfaces/IThickness.ts +1 -1
  165. package/{lib → src}/webcomponent/DockSpawnTsWebcomponent.d.ts +6 -10
  166. package/src/webcomponent/DockSpawnTsWebcomponent.d.ts.map +1 -0
  167. package/src/webcomponent/DockSpawnTsWebcomponent.js +178 -0
  168. package/src/webcomponent/DockSpawnTsWebcomponent.ts +207 -243
  169. package/src/webcomponent/styles.d.ts.map +1 -0
  170. package/{lib → src}/webcomponent/styles.js +2 -1
  171. package/tsconfig.json +13 -26
  172. package/.eslintrc.json +0 -47
  173. package/lib/BrowserDialogHelper.d.ts.map +0 -1
  174. package/lib/ContainerType.d.ts.map +0 -1
  175. package/lib/Dialog.d.ts.map +0 -1
  176. package/lib/DockConfig.d.ts.map +0 -1
  177. package/lib/DockGraphDeserializer.d.ts.map +0 -1
  178. package/lib/DockGraphDeserializer.js +0 -114
  179. package/lib/DockGraphSerializer.d.ts +0 -14
  180. package/lib/DockGraphSerializer.d.ts.map +0 -1
  181. package/lib/DockLayoutEngine.d.ts.map +0 -1
  182. package/lib/DockManager.d.ts.map +0 -1
  183. package/lib/DockManagerContext.d.ts.map +0 -1
  184. package/lib/DockModel.d.ts.map +0 -1
  185. package/lib/DockNode.d.ts.map +0 -1
  186. package/lib/DockWheel.d.ts.map +0 -1
  187. package/lib/DockWheelItem.d.ts.map +0 -1
  188. package/lib/DocumentManagerContainer.d.ts.map +0 -1
  189. package/lib/DocumentTabPage.d.ts.map +0 -1
  190. package/lib/DraggableContainer.d.ts.map +0 -1
  191. package/lib/EventHandler.d.ts.map +0 -1
  192. package/lib/FillDockContainer.d.ts.map +0 -1
  193. package/lib/HorizontalDockContainer.d.ts +0 -7
  194. package/lib/HorizontalDockContainer.d.ts.map +0 -1
  195. package/lib/PanelContainer.d.ts.map +0 -1
  196. package/lib/Point.d.ts.map +0 -1
  197. package/lib/ResizableContainer.d.ts.map +0 -1
  198. package/lib/ResizeHandle.d.ts.map +0 -1
  199. package/lib/SplitterBar.d.ts.map +0 -1
  200. package/lib/SplitterDockContainer.d.ts.map +0 -1
  201. package/lib/SplitterPanel.d.ts.map +0 -1
  202. package/lib/TabHandle.d.ts.map +0 -1
  203. package/lib/TabHost.d.ts.map +0 -1
  204. package/lib/TabPage.d.ts.map +0 -1
  205. package/lib/UndockInitiator.d.ts.map +0 -1
  206. package/lib/Utils.d.ts.map +0 -1
  207. package/lib/VerticalDockContainer.d.ts +0 -7
  208. package/lib/VerticalDockContainer.d.ts.map +0 -1
  209. package/lib/enums/PanelType.d.ts.map +0 -1
  210. package/lib/enums/TabHostDirection.d.ts.map +0 -1
  211. package/lib/enums/WheelTypes.d.ts.map +0 -1
  212. package/lib/i18n/Defaults.d.ts.map +0 -1
  213. package/lib/i18n/Localizer.d.ts.map +0 -1
  214. package/lib/index.d.ts.map +0 -1
  215. package/lib/interfaces/IDockContainer.d.ts.map +0 -1
  216. package/lib/interfaces/IDockContainerWithSize.d.ts +0 -6
  217. package/lib/interfaces/IDockContainerWithSize.d.ts.map +0 -1
  218. package/lib/interfaces/ILayoutEventListener.d.ts.map +0 -1
  219. package/lib/interfaces/IMouseOrTouchEvent.d.ts.map +0 -1
  220. package/lib/interfaces/INodeInfo.d.ts +0 -8
  221. package/lib/interfaces/INodeInfo.d.ts.map +0 -1
  222. package/lib/interfaces/IPanelInfo.d.ts +0 -10
  223. package/lib/interfaces/IPanelInfo.d.ts.map +0 -1
  224. package/lib/interfaces/IRectangle.d.ts.map +0 -1
  225. package/lib/interfaces/ISize.d.ts.map +0 -1
  226. package/lib/interfaces/IState.d.ts.map +0 -1
  227. package/lib/interfaces/IThickness.d.ts.map +0 -1
  228. package/lib/webcomponent/DockSpawnTsWebcomponent.d.ts.map +0 -1
  229. package/lib/webcomponent/DockSpawnTsWebcomponent.js +0 -209
  230. package/lib/webcomponent/styles.d.ts.map +0 -1
  231. package/tsconfig.tsbuildinfo +0 -1
  232. /package/{lib → src}/BrowserDialogHelper.d.ts +0 -0
  233. /package/{lib → src}/ContainerType.d.ts +0 -0
  234. /package/{lib → src}/ContainerType.js +0 -0
  235. /package/{lib → src}/DockConfig.d.ts +0 -0
  236. /package/{lib → src}/EventHandler.d.ts +0 -0
  237. /package/{lib → src}/Point.d.ts +0 -0
  238. /package/{lib → src}/Utils.d.ts +0 -0
  239. /package/{lib → src}/enums/PanelType.d.ts +0 -0
  240. /package/{lib → src}/enums/PanelType.js +0 -0
  241. /package/{lib → src}/enums/TabHostDirection.d.ts +0 -0
  242. /package/{lib → src}/enums/TabHostDirection.js +0 -0
  243. /package/{lib → src}/enums/WheelTypes.d.ts +0 -0
  244. /package/{lib → src}/enums/WheelTypes.js +0 -0
  245. /package/{lib → src}/i18n/Defaults.d.ts +0 -0
  246. /package/{lib → src}/i18n/Defaults.js +0 -0
  247. /package/{lib → src}/index.d.ts +0 -0
  248. /package/{lib → src}/index.js +0 -0
  249. /package/{lib → src}/interfaces/IDockContainer.js +0 -0
  250. /package/{lib → src}/interfaces/IDockContainerWithSize.js +0 -0
  251. /package/{lib → src}/interfaces/ILayoutEventListener.js +0 -0
  252. /package/{lib → src}/interfaces/IMouseOrTouchEvent.d.ts +0 -0
  253. /package/{lib → src}/interfaces/IMouseOrTouchEvent.js +0 -0
  254. /package/{lib → src}/interfaces/INodeInfo.js +0 -0
  255. /package/{lib → src}/interfaces/IPanelInfo.js +0 -0
  256. /package/{lib → src}/interfaces/IRectangle.d.ts +0 -0
  257. /package/{lib → src}/interfaces/IRectangle.js +0 -0
  258. /package/{lib → src}/interfaces/ISize.d.ts +0 -0
  259. /package/{lib → src}/interfaces/ISize.js +0 -0
  260. /package/{lib → src}/interfaces/IState.js +0 -0
  261. /package/{lib → src}/interfaces/IThickness.d.ts +0 -0
  262. /package/{lib → src}/interfaces/IThickness.js +0 -0
  263. /package/{lib → src}/webcomponent/styles.d.ts +0 -0
@@ -1,24 +1,24 @@
1
- import {DockWheel} from './DockWheel.js';
2
- import {Utils} from './Utils.js';
3
- import {Point} from './Point.js';
4
- import {DockManagerContext} from './DockManagerContext.js';
5
- import {DockNode} from './DockNode.js';
6
- import {DockLayoutEngine} from './DockLayoutEngine.js';
7
- import {EventHandler} from './EventHandler.js';
8
- import {Dialog} from './Dialog.js';
9
- import {DockGraphSerializer} from './DockGraphSerializer.js';
10
- import {DockGraphDeserializer} from './DockGraphDeserializer.js';
11
- import {IDockContainer} from './interfaces/IDockContainer.js';
12
- import {TabPage} from './TabPage.js';
13
- import {SplitterDockContainer} from './SplitterDockContainer.js';
14
- import {PanelContainer} from './PanelContainer.js';
15
- import {FillDockContainer} from './FillDockContainer.js';
16
- import {ILayoutEventListener} from './interfaces/ILayoutEventListener.js';
17
- import {DockModel} from './DockModel.js';
18
- import {IDockContainerWithSize} from './interfaces/IDockContainerWithSize.js';
19
- import {DockConfig} from './DockConfig.js';
20
- import {PanelType} from './enums/PanelType.js';
21
- import {IState} from './interfaces/IState.js';
1
+ import { DockWheel } from "./DockWheel";
2
+ import { Utils } from "./Utils";
3
+ import { Point } from "./Point";
4
+ import { DockManagerContext } from "./DockManagerContext";
5
+ import { DockNode } from "./DockNode";
6
+ import { DockLayoutEngine } from "./DockLayoutEngine";
7
+ import { EventHandler } from "./EventHandler";
8
+ import { Dialog } from "./Dialog";
9
+ import { DockGraphSerializer } from "./DockGraphSerializer";
10
+ import { DockGraphDeserializer } from "./DockGraphDeserializer";
11
+ import { IDockContainer } from "./interfaces/IDockContainer";
12
+ import { TabPage } from "./TabPage";
13
+ import { SplitterDockContainer } from "./SplitterDockContainer";
14
+ import { PanelContainer } from "./PanelContainer";
15
+ import { FillDockContainer } from "./FillDockContainer";
16
+ import { ILayoutEventListener } from "./interfaces/ILayoutEventListener";
17
+ import { DockModel } from "./DockModel";
18
+ import { IDockContainerWithSize } from "./interfaces/IDockContainerWithSize";
19
+ import { DockConfig } from "./DockConfig";
20
+ import { PanelType } from "./enums/PanelType";
21
+ import { IState } from "./interfaces/IState";
22
22
 
23
23
  /**
24
24
  * Dock manager manages all the dock panels in a hierarchy, similar to visual studio.
@@ -26,856 +26,882 @@ import {IState} from './interfaces/IState.js';
26
26
  * Initially the document manager takes up the central space and acts as the root node
27
27
  */
28
28
  export class DockManager {
29
- public element: HTMLElement;
30
- public context: DockManagerContext;
31
- public dockWheel: DockWheel;
32
- public layoutEngine: DockLayoutEngine;
33
- public mouseMoveHandler: EventHandler;
34
- public touchMoveHandler: EventHandler;
35
- public layoutEventListeners: ILayoutEventListener[];
36
- public closePanelContainerCallback: (panelContainer: PanelContainer) => Promise<boolean>;
37
- public defaultDialogPosition: Point;
38
- public backgroundContext: HTMLElement;
39
- public zIndexCounter: number;
40
- public zIndexTabHost: number;
41
- public zIndexTabHandle: number;
42
- public zIndexDialogCounter: number;
43
- public onKeyPressBound: any;
44
- public iframes: HTMLIFrameElement[];
45
- public _undockEnabled: boolean;
46
- public getElementCallback: (state: IState) => Promise<{ element: HTMLElement, title: string }>;
47
-
48
- private _config: DockConfig;
49
- private _activePanel: PanelContainer;
50
- private _lastPanelNotADialog: PanelContainer;
51
-
52
- private _activeDocument: PanelContainer;
53
-
54
- constructor(element: HTMLElement, config?: DockConfig) {
55
- if (element === undefined)
56
- throw new Error('Invalid Dock Manager element provided');
57
-
58
- this._config = Object.assign(new DockConfig(), config);
59
-
60
- this.element = element;
61
- this.context = this.dockWheel = this.layoutEngine = this.mouseMoveHandler = this.touchMoveHandler = undefined;
62
- this.layoutEventListeners = [];
63
-
64
- this.defaultDialogPosition = new Point(0, 0);
65
- }
66
-
67
- get config(): DockConfig {
68
- return this._config;
69
- }
70
-
71
- initialize() {
72
- this.backgroundContext = this.element.children[0] as HTMLElement;
73
- this.context = new DockManagerContext(this);
74
- const documentNode = new DockNode(this.context.documentManagerView);
75
- this.context.model.rootNode = documentNode;
76
- this.context.model.documentManagerNode = documentNode;
77
- this.context.model.dialogs = [];
78
- this.setRootNode(this.context.model.rootNode);
79
- // Resize the layout
80
- this.resize(this.element.clientWidth, this.element.clientHeight);
81
- this.dockWheel = new DockWheel(this);
82
- this.layoutEngine = new DockLayoutEngine(this);
83
- this._undockEnabled = true;
84
- this.rebuildLayout(this.context.model.rootNode);
85
- this.zIndexCounter = 1001;
86
- this.zIndexTabHost = 1000;
87
- this.zIndexTabHandle = 100;
88
- this.zIndexDialogCounter = 10001;
89
- if (this.backgroundContext != null) {
90
- (<FillDockContainer> this.context.model.rootNode.container).tabHost.hostElement
91
- .insertBefore(this.backgroundContext, (<FillDockContainer> this.context.model.rootNode.container).tabHost.hostElement.firstChild);
92
- }
93
-
94
- this.onKeyPressBound = this.onKeyPress.bind(this);
95
- this.element.addEventListener('keydown', this.onKeyPressBound);
96
- }
97
-
98
- onKeyPress(e: KeyboardEvent) {
99
- if (e.key == 'Escape' && this.activePanel && !this.activePanel._hideCloseButton) {
100
- if ((this.activePanel.isDialog && this._config.escClosesDialog) || (!this.activePanel.isDialog && this._config.escClosesWindow)) {
101
- const panel = this.activePanel;
102
- this.activePanel = null;
103
- panel.close();
104
- }
105
- }
106
- }
107
-
108
- checkXBounds(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeWest: boolean, resizeEast: boolean) {
109
- if (this._config.moveOnlyWithinDockConatiner)
110
- return this.checkXBoundsWithinDockContainer(container, currentMousePosition, previousMousePosition, resizeWest, resizeEast);
111
-
112
- const rect = this.element.getBoundingClientRect();
113
- let dx = Math.floor(currentMousePosition.x - previousMousePosition.x);
114
- const leftBounds = container.offsetLeft + container.offsetWidth + dx + rect.left < 40; // || (container.offsetLeft + container.offsetWidth + dx - 40 ) < 0;
115
- const rightBounds = container.offsetLeft + dx + rect.left > (window.innerWidth - 40);
116
- if (leftBounds) {
117
- previousMousePosition.x = currentMousePosition.x;
118
- dx = 0;
119
- const d = 40 - (container.offsetWidth + container.offsetLeft + rect.left);
120
- if (d > 0)
121
- dx = d;
122
- } else if (rightBounds) {
123
- previousMousePosition.x = currentMousePosition.x;
124
- dx = 0;
125
- const d = (window.innerWidth - 40) - container.offsetLeft - rect.left;
126
- if (d > 0)
127
- dx = d;
128
- }
129
-
130
- return dx;
131
- }
132
-
133
- checkXBoundsWithinDockContainer(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeWest: boolean, resizeEast: boolean) {
134
- let dx = currentMousePosition.x - previousMousePosition.x;
135
- const bbOuter = this.element.getBoundingClientRect();
136
- const bbInner = container.getBoundingClientRect();
137
- const leftBounds = dx < 0 && bbInner.left + dx < bbOuter.left && !resizeEast;
138
- const rightBounds = dx > 0 && bbInner.right + dx > bbOuter.right && !resizeWest;
139
-
140
- if (leftBounds) {
141
- currentMousePosition.x -= dx;
142
- dx = bbOuter.left - bbInner.left;
143
- currentMousePosition.x -= dx;
144
- } else if (rightBounds) {
145
- currentMousePosition.x -= dx;
146
- dx = bbOuter.right - bbInner.right;
147
- currentMousePosition.x -= dx;
148
- }
149
- return dx;
150
- }
151
-
152
- checkYBounds(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeNorth: boolean, resizeSouth: boolean) {
153
- if (this._config.moveOnlyWithinDockConatiner)
154
- return this.checkYBoundsWithinDockContainer(container, currentMousePosition, previousMousePosition, resizeNorth, resizeSouth);
155
-
156
- const rect = this.element.getBoundingClientRect();
157
- let dy = Math.floor(currentMousePosition.y - previousMousePosition.y);
158
- const topBounds = container.offsetTop + dy + rect.top < 0;
159
- const bottomBounds = container.offsetTop + dy + rect.top > (window.innerHeight - 16);
160
- if (topBounds) {
161
- previousMousePosition.y = currentMousePosition.y;
162
- dy = 0;
163
- } else if (bottomBounds) {
164
- previousMousePosition.y = currentMousePosition.y;
165
- dy = 0;
166
- const d = (window.innerHeight - 16) - container.offsetTop - rect.top;
167
- if (d > 0)
168
- dy = d;
169
- }
170
- return dy;
171
- }
172
-
173
- checkYBoundsWithinDockContainer(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeNorth: boolean, resizeSouth: boolean) {
174
- let dy = currentMousePosition.y - previousMousePosition.y;
175
- const bbOuter = this.element.getBoundingClientRect();
176
- const bbInner = container.getBoundingClientRect();
177
- const topBounds = dy < 0 && bbInner.top + dy < bbOuter.top && !resizeSouth;
178
- const bottomBounds = dy > 0 && bbInner.bottom + dy > bbOuter.bottom && !resizeNorth;
179
-
180
- if (topBounds) {
181
- currentMousePosition.y -= dy;
182
- dy = bbOuter.top - bbInner.top;
183
- currentMousePosition.y -= dy;
184
- } else if (bottomBounds) {
185
- currentMousePosition.y -= dy;
186
- dy = bbOuter.bottom - bbInner.bottom;
187
- currentMousePosition.y -= dy;
188
- }
189
- return dy;
190
- }
191
-
192
- rebuildLayout(node: DockNode) {
193
- node.children.forEach((child) => {
194
- this.rebuildLayout(child);
195
- });
196
- node.performLayout(false);
197
- }
198
-
199
- invalidate() {
200
- this.resize(this.element.clientWidth, this.element.clientHeight);
201
- }
202
-
203
- resize(width: number, height: number) {
204
- this.element.style.width = width + 'px';
205
- this.element.style.height = height + 'px';
206
- this.context.model.rootNode.container.resize(width, height);
207
-
208
- let offsetX = 0; let offsetY = 0;
209
- for (const dialog of this.context.model.dialogs) {
210
- if (dialog.position.x > this.element.clientWidth || dialog.position.y > this.element.clientHeight) {
211
- if (offsetX > this.element.clientWidth || offsetY > this.element.clientHeight)
212
- offsetX = 0, offsetY = 0;
213
- dialog.setPosition(100 + offsetX, 100 + offsetY);
214
- offsetX += 100;
215
- offsetY += 100;
216
- }
217
- }
218
- }
219
-
220
- /**
29
+
30
+ public element: HTMLElement;
31
+ public context: DockManagerContext;
32
+ public dockWheel: DockWheel;
33
+ public layoutEngine: DockLayoutEngine;
34
+ public mouseMoveHandler: EventHandler;
35
+ public touchMoveHandler: EventHandler;
36
+ public layoutEventListeners: ILayoutEventListener[];
37
+ public closePanelContainerCallback: (panelContainer: PanelContainer) => Promise<boolean>;
38
+ public defaultDialogPosition: Point;
39
+ public backgroundContext: HTMLElement;
40
+ public zIndexCounter: number;
41
+ public zIndexTabHost: number;
42
+ public zIndexTabHandle: number;
43
+ public zIndexDialogCounter: number;
44
+ public onKeyPressBound: any;
45
+ public iframes: HTMLIFrameElement[];
46
+ public _undockEnabled: boolean;
47
+ public getElementCallback: (state: IState) => Promise<{ element: HTMLElement, title: string }>;
48
+
49
+ private _config: DockConfig;
50
+ private _activePanel: PanelContainer;
51
+ private _lastPanelNotADialog: PanelContainer;
52
+
53
+ private _activeDocument: PanelContainer;
54
+
55
+ constructor(element: HTMLElement, config?: DockConfig) {
56
+ if (element === undefined)
57
+ throw new Error('Invalid Dock Manager element provided');
58
+
59
+ this._config = Object.assign(new DockConfig(), config);
60
+
61
+ this.element = element;
62
+ this.context = this.dockWheel = this.layoutEngine = this.mouseMoveHandler = this.touchMoveHandler = undefined;
63
+ this.layoutEventListeners = [];
64
+
65
+ this.defaultDialogPosition = new Point(0, 0);
66
+ }
67
+
68
+ get config(): DockConfig {
69
+ return this._config;
70
+ }
71
+
72
+ initialize() {
73
+ this.backgroundContext = this.element.children[0] as HTMLElement;
74
+ this.context = new DockManagerContext(this);
75
+ let documentNode = new DockNode(this.context.documentManagerView);
76
+ this.context.model.rootNode = documentNode;
77
+ this.context.model.documentManagerNode = documentNode;
78
+ this.context.model.dialogs = [];
79
+ this.setRootNode(this.context.model.rootNode);
80
+ // Resize the layout
81
+ this.resize(this.element.clientWidth, this.element.clientHeight);
82
+ this.dockWheel = new DockWheel(this);
83
+ this.layoutEngine = new DockLayoutEngine(this);
84
+ this._undockEnabled = true;
85
+ this.rebuildLayout(this.context.model.rootNode);
86
+ this.zIndexCounter = 1001;
87
+ this.zIndexTabHost = 1000;
88
+ this.zIndexTabHandle = 100;
89
+ this.zIndexDialogCounter = 10001;
90
+ if (this.backgroundContext != null) {
91
+ (<FillDockContainer>this.context.model.rootNode.container).tabHost.hostElement
92
+ .insertBefore(this.backgroundContext, (<FillDockContainer>this.context.model.rootNode.container).tabHost.hostElement.firstChild);
93
+ }
94
+
95
+ this.onKeyPressBound = this.onKeyPress.bind(this);
96
+ this.element.addEventListener('keydown', this.onKeyPressBound);
97
+ }
98
+
99
+ onKeyPress(e: KeyboardEvent) {
100
+ if (e.key == "Escape" && this.activePanel && !this.activePanel._hideCloseButton) {
101
+ if ((this.activePanel.isDialog && this._config.escClosesDialog) || (!this.activePanel.isDialog && this._config.escClosesWindow)) {
102
+ let panel = this.activePanel;
103
+ this.activePanel = null;
104
+ panel.close();
105
+ }
106
+ }
107
+ }
108
+
109
+ checkXBounds(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeWest: boolean, resizeEast: boolean) {
110
+ if (this._config.moveOnlyWithinDockConatiner)
111
+ return this.checkXBoundsWithinDockContainer(container, currentMousePosition, previousMousePosition, resizeWest, resizeEast);
112
+
113
+ let rect = this.element.getBoundingClientRect();
114
+ let dx = Math.floor(currentMousePosition.x - previousMousePosition.x);
115
+ let leftBounds = container.offsetLeft + container.offsetWidth + dx + rect.left < 40; // || (container.offsetLeft + container.offsetWidth + dx - 40 ) < 0;
116
+ let rightBounds = container.offsetLeft + dx + rect.left > (window.innerWidth - 40);
117
+ if (leftBounds) {
118
+ previousMousePosition.x = currentMousePosition.x;
119
+ dx = 0;
120
+ let d = 40 - (container.offsetWidth + container.offsetLeft + rect.left);
121
+ if (d > 0)
122
+ dx = d;
123
+ } else if (rightBounds) {
124
+ previousMousePosition.x = currentMousePosition.x;
125
+ dx = 0;
126
+ let d = (window.innerWidth - 40) - container.offsetLeft - rect.left;
127
+ if (d > 0)
128
+ dx = d;
129
+ }
130
+
131
+ return dx;
132
+ }
133
+
134
+ checkXBoundsWithinDockContainer(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeWest: boolean, resizeEast: boolean) {
135
+ let dx = currentMousePosition.x - previousMousePosition.x;
136
+ let bbOuter = this.element.getBoundingClientRect();
137
+ let bbInner = container.getBoundingClientRect();
138
+ let leftBounds = dx < 0 && bbInner.left + dx < bbOuter.left && !resizeEast;
139
+ let rightBounds = dx > 0 && bbInner.right + dx > bbOuter.right && !resizeWest;
140
+
141
+ if (leftBounds) {
142
+ currentMousePosition.x -= dx;
143
+ dx = bbOuter.left - bbInner.left;
144
+ currentMousePosition.x -= dx;
145
+ } else if (rightBounds) {
146
+ currentMousePosition.x -= dx;
147
+ dx = bbOuter.right - bbInner.right;
148
+ currentMousePosition.x -= dx;
149
+ }
150
+ return dx;
151
+ }
152
+
153
+ checkYBounds(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeNorth: boolean, resizeSouth: boolean) {
154
+ if (this._config.moveOnlyWithinDockConatiner)
155
+ return this.checkYBoundsWithinDockContainer(container, currentMousePosition, previousMousePosition, resizeNorth, resizeSouth);
156
+
157
+ let rect = this.element.getBoundingClientRect();
158
+ let dy = Math.floor(currentMousePosition.y - previousMousePosition.y);
159
+ let topBounds = container.offsetTop + dy + rect.top < 0;
160
+ let bottomBounds = container.offsetTop + dy + rect.top > (window.innerHeight - 16);
161
+ if (topBounds) {
162
+ previousMousePosition.y = currentMousePosition.y;
163
+ dy = 0;
164
+ } else if (bottomBounds) {
165
+ previousMousePosition.y = currentMousePosition.y;
166
+ dy = 0;
167
+ let d = (window.innerHeight - 16) - container.offsetTop - rect.top;
168
+ if (d > 0)
169
+ dy = d;
170
+ }
171
+ return dy;
172
+ }
173
+
174
+ checkYBoundsWithinDockContainer(container: HTMLElement, currentMousePosition: Point, previousMousePosition: Point, resizeNorth: boolean, resizeSouth: boolean) {
175
+ let dy = currentMousePosition.y - previousMousePosition.y;
176
+ let bbOuter = this.element.getBoundingClientRect();
177
+ let bbInner = container.getBoundingClientRect();
178
+ let topBounds = dy < 0 && bbInner.top + dy < bbOuter.top && !resizeSouth;
179
+ let bottomBounds = dy > 0 && bbInner.bottom + dy > bbOuter.bottom && !resizeNorth;
180
+
181
+ if (topBounds) {
182
+ currentMousePosition.y -= dy;
183
+ dy = bbOuter.top - bbInner.top;
184
+ currentMousePosition.y -= dy;
185
+ } else if (bottomBounds) {
186
+ currentMousePosition.y -= dy;
187
+ dy = bbOuter.bottom - bbInner.bottom;
188
+ currentMousePosition.y -= dy;
189
+ }
190
+ return dy;
191
+ }
192
+
193
+ rebuildLayout(node: DockNode) {
194
+ node.children.forEach((child) => {
195
+ this.rebuildLayout(child);
196
+ });
197
+ node.performLayout(false);
198
+ }
199
+
200
+ invalidate() {
201
+ this.resize(this.element.clientWidth, this.element.clientHeight);
202
+ }
203
+
204
+ resize(width: number, height: number) {
205
+ this.element.style.width = width + 'px';
206
+ this.element.style.height = height + 'px';
207
+ this.context.model.rootNode.container.resize(width, height);
208
+
209
+ let offsetX = 0, offsetY = 0;
210
+ for (let dialog of this.context.model.dialogs) {
211
+ if (dialog.position.x > this.element.clientWidth || dialog.position.y > this.element.clientHeight) {
212
+ if (offsetX > this.element.clientWidth || offsetY > this.element.clientHeight)
213
+ offsetX = 0, offsetY = 0;
214
+ dialog.setPosition(100 + offsetX, 100 + offsetY);
215
+ offsetX += 100;
216
+ offsetY += 100;
217
+ }
218
+ }
219
+ }
220
+
221
+ /**
221
222
  * Reset the dock model . This happens when the state is loaded from json
222
223
  */
223
- setModel(model: DockModel) {
224
- Utils.removeNode(this.context.documentManagerView.containerElement);
225
- this.context.model = model;
226
- this.setRootNode(model.rootNode);
227
-
228
- this.rebuildLayout(model.rootNode);
229
- this.loadResize(model.rootNode);
230
- // this.invalidate();
231
- }
232
-
233
- loadResize(node: DockNode) {
234
- node.children.reverse().forEach((child) => {
235
- this.loadResize(child);
236
- node.container.setActiveChild(child.container);
237
- });
238
- node.children.reverse();
239
- const container = node.container as IDockContainerWithSize;
240
- node.container.resize(container.state.width, container.state.height);
241
- // node.performLayout();
242
- }
243
-
244
-
245
- setRootNode(node: DockNode) {
246
- // if (this.context.model.rootNode)
247
- // {
248
- // // detach it from the dock manager's base element
249
- // context.model.rootNode.detachFromParent();
250
- // }
251
-
252
- // Attach the new node to the dock manager's base element and set as root node
253
- node.detachFromParent();
254
- this.context.model.rootNode = node;
255
- this.element.appendChild(node.container.containerElement);
256
- }
257
-
258
- _onDialogDragStarted(sender: Dialog, e) {
259
- this.dockWheel.activeNode = this._findNodeOnPoint(e.clientX, e.clientY);
260
- this.dockWheel.activeDialog = sender;
261
- if (sender.noDocking == null || sender.noDocking !== true)
262
- this.dockWheel.showWheel();
263
- if (this.mouseMoveHandler) {
264
- this.mouseMoveHandler.cancel();
265
- delete this.mouseMoveHandler;
266
- }
267
- if (this.touchMoveHandler) {
268
- this.touchMoveHandler.cancel();
269
- delete this.touchMoveHandler;
270
- }
271
- this.mouseMoveHandler = new EventHandler(window, 'mousemove', this._onMouseMoved.bind(this));
272
- this.touchMoveHandler = new EventHandler(window, 'touchmove', this._onMouseMoved.bind(this));
273
- }
274
-
275
- _onDialogDragEnded(sender: Dialog, e) {
276
- if (this.mouseMoveHandler) {
277
- this.mouseMoveHandler.cancel();
278
- delete this.mouseMoveHandler;
279
- }
280
- if (this.touchMoveHandler) {
281
- this.touchMoveHandler.cancel();
282
- delete this.touchMoveHandler;
283
- }
284
- this.dockWheel.onDialogDropped(sender);
285
- this.dockWheel.hideWheel();
286
- delete this.dockWheel.activeDialog;
287
- //TODO: not so good
288
- sender.saveState(sender.elementDialog.offsetLeft, sender.elementDialog.offsetTop);
289
- }
290
-
291
- private _onMouseMoved(e) {
292
- if (e.changedTouches != null) { // TouchMove Event
293
- e = e.changedTouches[0];
294
- }
295
- this.dockWheel.activeNode = this._findNodeOnPoint(e.clientX, e.clientY);
296
- }
297
-
298
- /**
224
+ setModel(model: DockModel) {
225
+ Utils.removeNode(this.context.documentManagerView.containerElement);
226
+ this.context.model = model;
227
+ this.setRootNode(model.rootNode);
228
+
229
+ this.rebuildLayout(model.rootNode);
230
+ this.loadResize(model.rootNode);
231
+ // this.invalidate();
232
+ }
233
+
234
+ loadResize(node: DockNode) {
235
+ node.children.reverse().forEach((child) => {
236
+ this.loadResize(child);
237
+ node.container.setActiveChild(child.container);
238
+ });
239
+ node.children.reverse();
240
+ let container = node.container as IDockContainerWithSize;
241
+ node.container.resize(container.state.width, container.state.height);
242
+ // node.performLayout();
243
+ }
244
+
245
+
246
+ setRootNode(node: DockNode) {
247
+ // if (this.context.model.rootNode)
248
+ // {
249
+ // // detach it from the dock manager's base element
250
+ // context.model.rootNode.detachFromParent();
251
+ // }
252
+
253
+ // Attach the new node to the dock manager's base element and set as root node
254
+ node.detachFromParent();
255
+ this.context.model.rootNode = node;
256
+ this.element.appendChild(node.container.containerElement);
257
+ }
258
+
259
+ _onDialogDragStarted(sender: Dialog, e) {
260
+ this.dockWheel.activeNode = this._findNodeOnPoint(e.clientX, e.clientY);
261
+ this.dockWheel.activeDialog = sender;
262
+ if (sender.noDocking == null || sender.noDocking !== true)
263
+ this.dockWheel.showWheel();
264
+ if (this.mouseMoveHandler) {
265
+ this.mouseMoveHandler.cancel();
266
+ delete this.mouseMoveHandler;
267
+ }
268
+ if (this.touchMoveHandler) {
269
+ this.touchMoveHandler.cancel();
270
+ delete this.touchMoveHandler;
271
+ }
272
+ this.mouseMoveHandler = new EventHandler(window, 'mousemove', this._onMouseMoved.bind(this));
273
+ this.touchMoveHandler = new EventHandler(window, 'touchmove', this._onMouseMoved.bind(this));
274
+ }
275
+
276
+ _onDialogDragEnded(sender: Dialog, e) {
277
+ if (this.mouseMoveHandler) {
278
+ this.mouseMoveHandler.cancel();
279
+ delete this.mouseMoveHandler;
280
+ }
281
+ if (this.touchMoveHandler) {
282
+ this.touchMoveHandler.cancel();
283
+ delete this.touchMoveHandler;
284
+ }
285
+ this.dockWheel.onDialogDropped(sender);
286
+ this.dockWheel.hideWheel();
287
+ delete this.dockWheel.activeDialog;
288
+ //TODO: not so good
289
+ sender.saveState(sender.elementDialog.offsetLeft, sender.elementDialog.offsetTop);
290
+ }
291
+
292
+ private _onMouseMoved(e) {
293
+ if (e.changedTouches != null) { // TouchMove Event
294
+ e = e.changedTouches[0];
295
+ }
296
+ this.dockWheel.activeNode = this._findNodeOnPoint(e.clientX, e.clientY);
297
+ }
298
+
299
+ /**
299
300
  * Perform a DFS (DeepFirstSearch) on the dock model's tree to find the
300
301
  * deepest level panel (i.e. the top-most non-overlapping panel)
301
302
  * that is under the mouse cursor
302
303
  * Retuns null if no node is found under this point
303
304
  */
304
- private _findNodeOnPoint(x: number, y: number) {
305
- const stack = [];
306
- stack.push(this.context.model.rootNode);
307
- let bestMatch;
308
-
309
- while (stack.length > 0) {
310
- const topNode = stack.pop();
311
-
312
- if (Utils.isPointInsideNode(x, y, topNode)) {
313
- // This node contains the point.
314
- bestMatch = topNode;
315
-
316
- // Keep looking future down
317
- [].push.apply(stack, topNode.children);
318
- }
319
- }
320
- return bestMatch;
321
- }
322
-
323
- /** Dock the [dialog] to the left of the [referenceNode] node */
324
- dockDialogLeft(referenceNode: DockNode, dialog: Dialog) {
325
- return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockLeft.bind(this.layoutEngine));
326
- }
327
-
328
- /** Dock the [dialog] to the right of the [referenceNode] node */
329
- dockDialogRight(referenceNode: DockNode, dialog: Dialog) {
330
- return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockRight.bind(this.layoutEngine));
331
- }
332
-
333
- /** Dock the [dialog] above the [referenceNode] node */
334
- dockDialogUp(referenceNode: DockNode, dialog: Dialog) {
335
- return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockUp.bind(this.layoutEngine));
336
- }
337
-
338
- /** Dock the [dialog] below the [referenceNode] node */
339
- dockDialogDown(referenceNode: DockNode, dialog: Dialog) {
340
- return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockDown.bind(this.layoutEngine));
341
- }
342
-
343
- /** Dock the [dialog] as a tab inside the [referenceNode] node */
344
- dockDialogFill(referenceNode: DockNode, dialog: Dialog) {
345
- return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockFill.bind(this.layoutEngine));
346
- }
347
-
348
- /** Dock the [container] to the left of the [referenceNode] node */
349
- dockLeft(referenceNode: DockNode, container: PanelContainer, ratio: number) {
350
- return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockLeft.bind(this.layoutEngine), false, ratio);
351
- }
352
-
353
- /** Dock the [container] to the right of the [referenceNode] node */
354
- dockRight(referenceNode: DockNode, container: PanelContainer, ratio: number) {
355
- return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockRight.bind(this.layoutEngine), true, ratio);
356
- }
357
-
358
- /** Dock the [container] above the [referenceNode] node */
359
- dockUp(referenceNode: DockNode, container: PanelContainer, ratio: number) {
360
- return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockUp.bind(this.layoutEngine), false, ratio);
361
- }
362
-
363
- /** Dock the [container] below the [referenceNode] node */
364
- dockDown(referenceNode: DockNode, container: PanelContainer, ratio: number) {
365
- return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockDown.bind(this.layoutEngine), true, ratio);
366
- }
367
-
368
- /** Dock the [container] as a tab inside the [referenceNode] node */
369
- dockFill(referenceNode: DockNode, container: PanelContainer) {
370
- return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockFill.bind(this.layoutEngine), false);
371
- }
372
-
373
- floatDialog(container: PanelContainer, x: number, y: number, grayoutParent?: PanelContainer, disableResize?: boolean): Dialog {
374
- let retdiag = undefined;
375
-
376
- //check the dialog do not already exist
377
- this.context.model.dialogs.forEach((dialog) => {
378
- if (container == dialog.panel) {
379
- dialog.show();
380
- dialog.setPosition(x, y);
381
- retdiag = dialog;
382
- }
383
- });
384
- if (retdiag)
385
- return retdiag;
386
- //try to undock just in case
387
- try {
388
- const node = this._findNodeFromContainer(container);
389
- this.layoutEngine.undock(node);
390
- } catch (err) { }
391
-
392
- const panel = container;
393
- Utils.removeNode(panel.elementPanel);
394
- panel.isDialog = true;
395
- const dialog = new Dialog(panel, this, grayoutParent, disableResize);
396
- dialog.setPosition(x, y);
397
- return dialog;
398
- }
399
-
400
- private _requestDockDialog(referenceNode: DockNode, dialog: Dialog, layoutDockFunction: (referenceNode: DockNode, newNode: DockNode) => void) {
401
- // Get the active dialog that was dragged on to the dock wheel
402
- const panel = dialog.panel;
403
- const newNode = new DockNode(panel);
404
- panel.prepareForDocking();
405
- panel.elementContentContainer.style.zIndex = '';
406
- dialog.destroy();
407
- layoutDockFunction(referenceNode, newNode);
408
- // this.invalidate();
409
- return newNode;
410
- }
411
-
412
- private _checkShowBackgroundContext() {
413
- if (this.backgroundContext != null) {
414
- if (this.context.model.documentManagerNode.children.length > 0)
415
- this.backgroundContext.style.display = 'none';
416
- else
417
- this.backgroundContext.style.display = 'block';
418
- }
419
- }
420
-
421
- private _requestDockContainer(referenceNode: DockNode, container: IDockContainer, layoutDockFunction: (referenceNode: DockNode, newNode: DockNode) => void, dockedToPrevious: boolean, ratio?: number) {
422
- // Get the active dialog that was dragged on to the dock wheel
423
- const newNode = new DockNode(container);
424
- if (container.containerType === 'panel') {
425
- const panel = container as PanelContainer;
426
- panel.prepareForDocking();
427
- Utils.removeNode(panel.elementPanel);
428
- }
429
-
430
- let ratios: number[] = null;
431
- let oldSplitter: SplitterDockContainer;
432
- if (referenceNode?.parent && referenceNode.parent.container) {
433
- oldSplitter = referenceNode.parent.container as SplitterDockContainer;
434
- if (oldSplitter.getRatios)
435
- ratios = oldSplitter.getRatios();
436
- }
437
-
438
- layoutDockFunction(referenceNode, newNode);
439
-
440
- if (ratio && newNode.parent && (newNode.parent.container.containerType === 'vertical' || newNode.parent.container.containerType === 'horizontal')) {
441
- const splitter = newNode.parent.container as SplitterDockContainer;
442
- if (ratios && oldSplitter == splitter) {
443
- if (dockedToPrevious) {
444
- for (let i = 0; i < ratios.length; i++)
445
- ratios[i] = ratios[i] - ratios[i] * ratio;
446
-
447
- ratios.push(ratio);
448
- } else {
449
- ratios[0] = ratios[0] - ratio;
450
- ratios.unshift(ratio);
305
+ private _findNodeOnPoint(x: number, y: number) {
306
+ let stack = [];
307
+ stack.push(this.context.model.rootNode);
308
+ let bestMatch;
309
+
310
+ while (stack.length > 0) {
311
+ let topNode = stack.pop();
312
+
313
+ if (Utils.isPointInsideNode(x, y, topNode)) {
314
+ // This node contains the point.
315
+ bestMatch = topNode;
316
+
317
+ // Keep looking future down
318
+ [].push.apply(stack, topNode.children);
319
+ }
451
320
  }
452
- splitter.setRatios(ratios);
453
- } else
454
- splitter.setContainerRatio(container, ratio);
321
+ return bestMatch;
455
322
  }
456
323
 
457
- this.rebuildLayout(this.context.model.rootNode);
458
- this.invalidate();
324
+ /** Dock the [dialog] to the left of the [referenceNode] node */
325
+ dockDialogLeft(referenceNode: DockNode, dialog: Dialog) {
326
+ return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockLeft.bind(this.layoutEngine));
327
+ }
459
328
 
460
- this._checkShowBackgroundContext();
329
+ /** Dock the [dialog] to the right of the [referenceNode] node */
330
+ dockDialogRight(referenceNode: DockNode, dialog: Dialog) {
331
+ return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockRight.bind(this.layoutEngine));
332
+ }
461
333
 
462
- return newNode;
463
- }
334
+ /** Dock the [dialog] above the [referenceNode] node */
335
+ dockDialogUp(referenceNode: DockNode, dialog: Dialog) {
336
+ return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockUp.bind(this.layoutEngine));
337
+ }
464
338
 
465
- _requestTabReorder(container: IDockContainer, e) {
466
- const node = this._findNodeFromContainer(container);
467
- this.layoutEngine.reorderTabs(node, e.handle, e.state, e.index);
468
- }
339
+ /** Dock the [dialog] below the [referenceNode] node */
340
+ dockDialogDown(referenceNode: DockNode, dialog: Dialog) {
341
+ return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockDown.bind(this.layoutEngine));
342
+ }
469
343
 
470
- /**
471
- * Undocks a panel and converts it into a floating dialog window
472
- * It is assumed that only leaf nodes (panels) can be undocked
473
- */
474
- requestUndockToDialog(container: PanelContainer, event, dragOffset: Point) {
475
- const node = this._findNodeFromContainer(container);
476
- this.layoutEngine.undock(node);
344
+ /** Dock the [dialog] as a tab inside the [referenceNode] node */
345
+ dockDialogFill(referenceNode: DockNode, dialog: Dialog) {
346
+ return this._requestDockDialog(referenceNode, dialog, this.layoutEngine.dockFill.bind(this.layoutEngine));
347
+ }
348
+
349
+ /** Dock the [container] to the left of the [referenceNode] node */
350
+ dockLeft(referenceNode: DockNode, container: PanelContainer, ratio: number) {
351
+ return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockLeft.bind(this.layoutEngine), false, ratio);
352
+ }
353
+
354
+ /** Dock the [container] to the right of the [referenceNode] node */
355
+ dockRight(referenceNode: DockNode, container: PanelContainer, ratio: number) {
356
+ return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockRight.bind(this.layoutEngine), true, ratio);
357
+ }
358
+
359
+ /** Dock the [container] above the [referenceNode] node */
360
+ dockUp(referenceNode: DockNode, container: PanelContainer, ratio: number) {
361
+ return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockUp.bind(this.layoutEngine), false, ratio);
362
+ }
363
+
364
+ /** Dock the [container] below the [referenceNode] node */
365
+ dockDown(referenceNode: DockNode, container: PanelContainer, ratio: number) {
366
+ return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockDown.bind(this.layoutEngine), true, ratio);
367
+ }
477
368
 
478
- const panelContainer = (<PanelContainer>node.container);
479
- panelContainer.elementPanel.style.display = 'block';
369
+ /** Dock the [container] as a tab inside the [referenceNode] node */
370
+ dockFill(referenceNode: DockNode, container: PanelContainer) {
371
+ return this._requestDockContainer(referenceNode, container, this.layoutEngine.dockFill.bind(this.layoutEngine), false);
372
+ }
480
373
 
481
- // Create a new dialog window for the undocked panel
482
- const dialog = new Dialog(panelContainer, this, null);
374
+ floatDialog(container: PanelContainer, x: number, y: number, grayoutParent?: PanelContainer, disableResize?: boolean): Dialog {
375
+ let retdiag = undefined;
376
+
377
+ //check the dialog do not already exist
378
+ this.context.model.dialogs.forEach((dialog) => {
379
+ if (container == dialog.panel) {
380
+ dialog.show();
381
+ dialog.setPosition(x, y);
382
+ retdiag = dialog;
383
+ }
384
+ });
385
+ if (retdiag)
386
+ return retdiag;
387
+ //try to undock just in case
388
+ try {
389
+ let node = this._findNodeFromContainer(container);
390
+ this.layoutEngine.undock(node);
391
+ } catch (err) { }
392
+
393
+ let panel = container;
394
+ Utils.removeNode(panel.elementPanel);
395
+ panel.isDialog = true;
396
+ let dialog = new Dialog(panel, this, grayoutParent, disableResize);
397
+ dialog.setPosition(x, y);
398
+ return dialog;
399
+ }
483
400
 
484
- if (panelContainer.lastDialogSize)
485
- dialog.resize(panelContainer.lastDialogSize.width, panelContainer.lastDialogSize.height);
401
+ private _requestDockDialog(referenceNode: DockNode, dialog: Dialog, layoutDockFunction: (referenceNode: DockNode, newNode: DockNode) => void) {
402
+ // Get the active dialog that was dragged on to the dock wheel
403
+ let panel = dialog.panel;
404
+ let newNode = new DockNode(panel);
405
+ panel.prepareForDocking();
406
+ panel.elementContentContainer.style.zIndex = '';
407
+ dialog.destroy();
408
+ layoutDockFunction(referenceNode, newNode);
409
+ // this.invalidate();
410
+ return newNode;
411
+ }
486
412
 
487
- if (event !== undefined) {
488
- // Adjust the relative position
489
- const dialogWidth = dialog.elementDialog.clientWidth;
490
- if (dragOffset.x > dialogWidth)
491
- dragOffset.x = 0.75 * dialogWidth;
492
- dialog.setPosition(
493
- event.clientX - dragOffset.x,
494
- event.clientY - dragOffset.y);
495
- dialog.draggable.onMouseDown(event);
413
+ private _checkShowBackgroundContext() {
414
+ if (this.backgroundContext != null) {
415
+ if (this.context.model.documentManagerNode.children.length > 0) {
416
+ this.backgroundContext.style.display = "none";
417
+ } else {
418
+ this.backgroundContext.style.display = "block";
419
+ }
420
+ }
496
421
  }
497
- return dialog;
498
- }
499
422
 
500
- /**
423
+ private _requestDockContainer(referenceNode: DockNode, container: IDockContainer, layoutDockFunction: (referenceNode: DockNode, newNode: DockNode) => void, dockedToPrevious: boolean, ratio?: number) {
424
+ // Get the active dialog that was dragged on to the dock wheel
425
+ let newNode = new DockNode(container);
426
+ if (container.containerType === 'panel') {
427
+ let panel = container as PanelContainer;
428
+ panel.prepareForDocking();
429
+ Utils.removeNode(panel.elementPanel);
430
+ }
431
+
432
+ let ratios: number[] = null;
433
+ let oldSplitter: SplitterDockContainer;
434
+ if (referenceNode?.parent && referenceNode.parent.container) {
435
+ oldSplitter = referenceNode.parent.container as SplitterDockContainer;
436
+ if (oldSplitter.getRatios)
437
+ ratios = oldSplitter.getRatios();
438
+ }
439
+
440
+ layoutDockFunction(referenceNode, newNode);
441
+
442
+ if (ratio && newNode.parent && (newNode.parent.container.containerType === 'vertical' || newNode.parent.container.containerType === 'horizontal')) {
443
+ let splitter = newNode.parent.container as SplitterDockContainer;
444
+ if (ratios && oldSplitter == splitter) {
445
+ if (dockedToPrevious) {
446
+ for (let i = 0; i < ratios.length; i++) {
447
+ ratios[i] = ratios[i] - ratios[i] * ratio;
448
+ }
449
+ ratios.push(ratio);
450
+ } else {
451
+ ratios[0] = ratios[0] - ratio;
452
+ ratios.unshift(ratio);
453
+ }
454
+ splitter.setRatios(ratios);
455
+ }
456
+ else
457
+ splitter.setContainerRatio(container, ratio);
458
+ }
459
+
460
+ this.rebuildLayout(this.context.model.rootNode);
461
+ this.invalidate();
462
+
463
+ this._checkShowBackgroundContext();
464
+
465
+ return newNode;
466
+ }
467
+
468
+ _requestTabReorder(container: IDockContainer, e) {
469
+ let node = this._findNodeFromContainer(container);
470
+ this.layoutEngine.reorderTabs(node, e.handle, e.state, e.index);
471
+ }
472
+
473
+ /**
474
+ * Undocks a panel and converts it into a floating dialog window
475
+ * It is assumed that only leaf nodes (panels) can be undocked
476
+ */
477
+ requestUndockToDialog(container: PanelContainer, event, dragOffset: Point) {
478
+ let node = this._findNodeFromContainer(container);
479
+ this.layoutEngine.undock(node);
480
+
481
+ let panelContainer = (<PanelContainer>node.container);
482
+ panelContainer.elementPanel.style.display = 'block';
483
+
484
+ // Create a new dialog window for the undocked panel
485
+ let dialog = new Dialog(panelContainer, this, null);
486
+
487
+ if (panelContainer.lastDialogSize)
488
+ dialog.resize(panelContainer.lastDialogSize.width, panelContainer.lastDialogSize.height);
489
+
490
+ if (event !== undefined) {
491
+ // Adjust the relative position
492
+ let dialogWidth = dialog.elementDialog.clientWidth;
493
+ if (dragOffset.x > dialogWidth)
494
+ dragOffset.x = 0.75 * dialogWidth;
495
+ dialog.setPosition(
496
+ event.clientX - dragOffset.x,
497
+ event.clientY - dragOffset.y);
498
+ dialog.draggable.onMouseDown(event);
499
+ }
500
+ return dialog;
501
+ }
502
+
503
+ /**
501
504
  * closes a Panel
502
505
  */
503
- requestClose(container: PanelContainer) {
504
- const node = this._findNodeFromContainer(container);
505
- this.layoutEngine.close(node);
506
- if (this.activePanel == container)
507
- this.activePanel = null;
508
- if (this._activeDocument == container) {
509
- const last = this._activeDocument;
510
- this._activeDocument = null;
511
- this.notifyOnActiveDocumentChange(null, last);
512
- }
513
- }
514
-
515
- /**
506
+ requestClose(container: PanelContainer) {
507
+ let node = this._findNodeFromContainer(container);
508
+ this.layoutEngine.close(node);
509
+ if (this.activePanel == container)
510
+ this.activePanel = null;
511
+ if (this._activeDocument == container) {
512
+ const last = this._activeDocument;
513
+ this._activeDocument = null;
514
+ this.notifyOnActiveDocumentChange(null, last);
515
+ }
516
+ }
517
+
518
+ /**
516
519
  * Opens a Element in a Dialog
517
520
  * It is assumed that only leaf nodes (panels) can be undocked
518
521
  */
519
- openInDialog(container: PanelContainer, event, dragOffset: Point, disableResize?: boolean) {
520
- // Create a new dialog window for the undocked panel
521
- const dialog = new Dialog(container, this, null, disableResize);
522
-
523
- if (event != null) {
524
- // Adjust the relative position
525
- const dialogWidth = dialog.elementDialog.clientWidth;
526
- if (dragOffset.x > dialogWidth)
527
- dragOffset.x = 0.75 * dialogWidth;
528
- dialog.setPosition(
529
- event.clientX - dragOffset.x,
530
- event.clientY - dragOffset.y);
531
- dialog.draggable.onMouseDown(event);
532
- }
533
- return dialog;
534
- }
535
-
536
- /** Undocks a panel and converts it into a floating dialog window
522
+ openInDialog(container: PanelContainer, event, dragOffset: Point, disableResize?: boolean) {
523
+ // Create a new dialog window for the undocked panel
524
+ let dialog = new Dialog(container, this, null, disableResize);
525
+
526
+ if (event != null) {
527
+ // Adjust the relative position
528
+ let dialogWidth = dialog.elementDialog.clientWidth;
529
+ if (dragOffset.x > dialogWidth)
530
+ dragOffset.x = 0.75 * dialogWidth;
531
+ dialog.setPosition(
532
+ event.clientX - dragOffset.x,
533
+ event.clientY - dragOffset.y);
534
+ dialog.draggable.onMouseDown(event);
535
+ }
536
+ return dialog;
537
+ }
538
+
539
+ /** Undocks a panel and converts it into a floating dialog window
537
540
  * It is assumed that only leaf nodes (panels) can be undocked
538
541
  */
539
- requestUndock(container: PanelContainer) {
540
- const node = this._findNodeFromContainer(container);
541
- this.layoutEngine.undock(node);
542
- }
542
+ requestUndock(container: PanelContainer) {
543
+ let node = this._findNodeFromContainer(container);
544
+ this.layoutEngine.undock(node);
545
+ }
543
546
 
544
- /**
547
+ /**
545
548
  * Removes a dock container from the dock layout hierarcy
546
549
  * Returns the node that was removed from the dock tree
547
550
  */
548
- requestRemove(container: PanelContainer) {
549
- const node = this._findNodeFromContainer(container);
550
- const parent = node.parent;
551
- node.detachFromParent();
552
- if (parent)
553
- this.rebuildLayout(parent);
554
- return node;
555
- }
556
-
557
- getNodeByElementId(id: string): DockNode {
558
- const stack = [];
559
- stack.push(this.context.model.rootNode);
560
-
561
- while (stack.length > 0) {
562
- const topNode = stack.pop();
563
-
564
- if (topNode.container instanceof PanelContainer) {
565
- if (topNode.container.elementContent.id === id)
566
- return topNode;
567
- if (topNode.container.elementContent instanceof HTMLSlotElement) {
568
- if ((<HTMLSlotElement>topNode.container.elementContent).assignedElements()?.[0]?.id === id)
569
- return topNode;
551
+ requestRemove(container: PanelContainer) {
552
+ let node = this._findNodeFromContainer(container);
553
+ let parent = node.parent;
554
+ node.detachFromParent();
555
+ if (parent)
556
+ this.rebuildLayout(parent);
557
+ return node;
558
+ }
559
+
560
+ getNodeByElementId(id: string): DockNode {
561
+ let stack = [];
562
+ stack.push(this.context.model.rootNode);
563
+
564
+ while (stack.length > 0) {
565
+ let topNode = stack.pop();
566
+
567
+ if (topNode.container instanceof PanelContainer) {
568
+ if (topNode.container.elementContent.id === id)
569
+ return topNode;
570
+ if (topNode.container.elementContent instanceof HTMLSlotElement) {
571
+ if ((<HTMLSlotElement>topNode.container.elementContent).assignedElements()?.[0]?.id === id)
572
+ return topNode;
573
+ }
574
+ }
575
+
576
+ [].push.apply(stack, topNode.children);
577
+ }
578
+
579
+ return null;
580
+ }
581
+
582
+ getNodeByElement(element: Element): DockNode {
583
+ let stack = [];
584
+ stack.push(this.context.model.rootNode);
585
+
586
+ while (stack.length > 0) {
587
+ let topNode = stack.pop();
588
+
589
+ if (topNode.container instanceof PanelContainer) {
590
+ if (topNode.container.elementContent === element)
591
+ return topNode;
592
+ if (topNode.container.elementContent instanceof HTMLSlotElement) {
593
+ if ((<HTMLSlotElement>topNode.container.elementContent).assignedElements()?.[0] === element)
594
+ return topNode;
595
+ }
596
+ }
597
+
598
+ [].push.apply(stack, topNode.children);
599
+ }
600
+
601
+ return null;
602
+ }
603
+
604
+ /** Finds the node that owns the specified [container] */
605
+ private _findNodeFromContainer(container: IDockContainer): DockNode {
606
+ //@ts-ignore
607
+ if (!container.title)
608
+ return this.findNodeFromContainerElement(container.containerElement);
609
+
610
+ let stack = [];
611
+ stack.push(this.context.model.rootNode);
612
+
613
+ while (stack.length > 0) {
614
+ let topNode = stack.pop();
615
+
616
+ //@ts-ignore
617
+ if (topNode.container.title === container.title)
618
+ return topNode;
619
+ [].push.apply(stack, topNode.children);
620
+ }
621
+
622
+ return null;
623
+ }
624
+
625
+ findNodeFromContainerElement(containerElement: HTMLElement) {
626
+ let stack: DockNode[] = [];
627
+ stack.push(this.context.model.rootNode);
628
+
629
+ while (stack.length > 0) {
630
+ let topNode = stack.pop();
631
+
632
+ if (topNode.container.containerElement === containerElement)
633
+ return topNode;
634
+ [].push.apply(stack, topNode.children);
635
+ }
636
+
637
+ return null;
638
+ }
639
+
640
+ addLayoutListener(listener: ILayoutEventListener) {
641
+ this.layoutEventListeners.push(listener);
642
+ }
643
+
644
+ removeLayoutListener(listener: ILayoutEventListener) {
645
+ this.layoutEventListeners.splice(this.layoutEventListeners.indexOf(listener), 1);
646
+ }
647
+
648
+ suspendLayout(panel: IDockContainer) {
649
+ this.layoutEventListeners.forEach((listener) => {
650
+ if (listener.onSuspendLayout) listener.onSuspendLayout(this, panel);
651
+ });
652
+ }
653
+
654
+ resumeLayout(panel: IDockContainer) {
655
+ this.layoutEventListeners.forEach((listener) => {
656
+ if (listener.onResumeLayout) listener.onResumeLayout(this, panel);
657
+ });
658
+ }
659
+
660
+ notifyOnDock(dockNode: DockNode) {
661
+ this._checkShowBackgroundContext();
662
+ this.layoutEventListeners.forEach((listener) => {
663
+ if (listener.onDock) {
664
+ listener.onDock(this, dockNode);
665
+ dockNode.container.resize(dockNode.container.width, dockNode.container.height);
666
+ }
667
+ });
668
+ }
669
+
670
+ notifyOnTabsReorder(dockNode: DockNode) {
671
+ this.layoutEventListeners.forEach((listener) => {
672
+ if (listener.onTabsReorder) {
673
+ listener.onTabsReorder(this, dockNode);
674
+ }
675
+ });
676
+ }
677
+
678
+ notifyOnUnDock(dockNode: DockNode) {
679
+ this._checkShowBackgroundContext();
680
+ this.layoutEventListeners.forEach((listener) => {
681
+ if (listener.onUndock) {
682
+ listener.onUndock(this, dockNode);
683
+ }
684
+ });
685
+ }
686
+
687
+ notifyOnClosePanel(panel: PanelContainer) {
688
+ this._checkShowBackgroundContext();
689
+ if (this.activePanel == panel)
690
+ this.activePanel = null;
691
+ if (this._activeDocument == panel) {
692
+ const last = this._activeDocument;
693
+ this._activeDocument = null;
694
+ this.notifyOnActiveDocumentChange(null, last);
570
695
  }
571
- }
696
+ this.layoutEventListeners.forEach((listener) => {
697
+ if (listener.onClosePanel) {
698
+ listener.onClosePanel(this, panel);
699
+ }
700
+ });
701
+ }
702
+
703
+ notifyOnCreateDialog(dialog: Dialog) {
704
+ this.layoutEventListeners.forEach((listener) => {
705
+ if (listener.onCreateDialog) {
706
+ listener.onCreateDialog(this, dialog);
707
+ }
708
+ });
709
+ }
710
+
711
+ notifyOnHideDialog(dialog: Dialog) {
712
+ this.layoutEventListeners.forEach((listener) => {
713
+ if (listener.onHideDialog) {
714
+ listener.onHideDialog(this, dialog);
715
+ }
716
+ });
717
+ }
718
+
719
+
720
+ notifyOnShowDialog(dialog: Dialog) {
721
+ this.layoutEventListeners.forEach((listener) => {
722
+ if (listener.onShowDialog) {
723
+ listener.onShowDialog(this, dialog);
724
+ }
725
+ });
726
+ }
727
+
728
+ notifyOnChangeDialogPosition(dialog: Dialog, x: number, y: number) {
729
+ this.layoutEventListeners.forEach((listener) => {
730
+ if (listener.onChangeDialogPosition) {
731
+ listener.onChangeDialogPosition(this, dialog, x, y);
732
+ }
733
+ });
734
+ }
735
+
736
+ notifyOnContainerResized(dockContainer: IDockContainer) {
737
+ this.layoutEventListeners.forEach((listener) => {
738
+ if (listener.onContainerResized) {
739
+ listener.onContainerResized(this, dockContainer);
740
+ }
741
+ });
742
+ }
743
+
744
+ notifyOnTabChange(tabpage: TabPage) {
745
+ this.layoutEventListeners.forEach((listener) => {
746
+ if (listener.onTabChanged) {
747
+ listener.onTabChanged(this, tabpage);
748
+ }
749
+ });
750
+ }
751
+
752
+ notifyOnActivePanelChange(panel: PanelContainer, oldActive: PanelContainer) {
753
+ this.layoutEventListeners.forEach((listener) => {
754
+ if (listener.onActivePanelChange) {
755
+ listener.onActivePanelChange(this, panel, oldActive);
756
+ }
757
+ });
758
+ }
759
+
760
+ notifyOnActiveDocumentChange(panel: PanelContainer, oldActive: PanelContainer) {
761
+ this.layoutEventListeners.forEach((listener) => {
762
+ if (listener.onActiveDocumentChange) {
763
+ listener.onActiveDocumentChange(this, panel, oldActive);
764
+ }
765
+ });
766
+ }
572
767
 
573
- [].push.apply(stack, topNode.children);
768
+ saveState() {
769
+ let serializer = new DockGraphSerializer();
770
+ return serializer.serialize(this.context.model);
574
771
  }
575
772
 
576
- return null;
577
- }
773
+ async loadState(json: string) {
774
+ let deserializer = new DockGraphDeserializer(this);
775
+ this.context.model = await deserializer.deserialize(json);
776
+ this.setModel(this.context.model);
777
+ }
778
+
779
+ getPanels() {
780
+ let panels: PanelContainer[] = [];
781
+ //all visible nodes
782
+ this._allPanels(this.context.model.rootNode, panels);
783
+
784
+ //all visible or not dialogs
785
+ this.context.model.dialogs.forEach((dialog) => {
786
+ //TODO: check visible
787
+ panels.push(dialog.panel);
788
+ });
789
+
790
+ return panels;
791
+ }
792
+
793
+ undockEnabled(state: boolean) {
794
+ this._undockEnabled = state;
795
+ this.getPanels().forEach((panel) => {
796
+ panel.canUndock(state);
797
+ });
798
+ }
799
+
800
+ lockDockState(state: boolean) {
801
+ this.undockEnabled(!state); // false - not enabled
802
+ this.hideCloseButton(state); //true - hide
803
+ }
578
804
 
579
- getNodeByElement(element: Element): DockNode {
580
- const stack = [];
581
- stack.push(this.context.model.rootNode);
805
+ hideCloseButton(state: boolean) {
806
+ this.getPanels().forEach((panel) => {
807
+ panel.hideCloseButton(state);
808
+ });
809
+ }
810
+
811
+ updatePanels(ids: string[]) {
812
+ let panels: PanelContainer[] = [];
813
+ //all visible nodes
814
+ this._allPanels(this.context.model.rootNode, panels);
815
+ //only remove
816
+ panels.forEach((panel) => {
817
+ if (!Utils.arrayContains(ids, panel.elementContent.id)) {
818
+ panel.close();
819
+ }
820
+ });
821
+
822
+ this.context.model.dialogs.forEach((dialog) => {
823
+ if (Utils.arrayContains(ids, dialog.panel.elementContent.id)) {
824
+ dialog.show();
825
+ }
826
+ else {
827
+ dialog.hide();
828
+ }
829
+ });
830
+ return panels;
831
+ }
582
832
 
583
- while (stack.length > 0) {
584
- const topNode = stack.pop();
833
+ getVisiblePanels(): PanelContainer[] {
834
+ let panels: PanelContainer[] = [];
835
+ //all visible nodes
836
+ this._allPanels(this.context.model.rootNode, panels);
585
837
 
586
- if (topNode.container instanceof PanelContainer) {
587
- if (topNode.container.elementContent === element)
588
- return topNode;
589
- if (topNode.container.elementContent instanceof HTMLSlotElement) {
590
- if ((<HTMLSlotElement>topNode.container.elementContent).assignedElements()?.[0] === element)
591
- return topNode;
838
+ //all visible
839
+ this.context.model.dialogs.forEach((dialog) => {
840
+ if (!dialog.isHidden) {
841
+ panels.push(dialog.panel);
842
+ }
843
+ });
844
+
845
+ return panels;
846
+ }
847
+
848
+ _allPanels(node: DockNode, panels: PanelContainer[]) {
849
+ node.children.forEach((child) => {
850
+ this._allPanels(child, panels);
851
+ });
852
+ if (node.container.containerType === 'panel') {
853
+ panels.push(node.container as PanelContainer);
592
854
  }
593
- }
594
-
595
- [].push.apply(stack, topNode.children);
596
- }
597
-
598
- return null;
599
- }
600
-
601
- /** Finds the node that owns the specified [container] */
602
- private _findNodeFromContainer(container: IDockContainer): DockNode {
603
- const stack = [];
604
- stack.push(this.context.model.rootNode);
605
-
606
- while (stack.length > 0) {
607
- const topNode = stack.pop();
608
-
609
- //@ts-ignore
610
- if (topNode.container.title === container.title)
611
- return topNode;
612
- [].push.apply(stack, topNode.children);
613
- }
614
-
615
- return null;
616
- }
617
-
618
- findNodeFromContainerElement(containerElement: HTMLElement) {
619
- const stack: DockNode[] = [];
620
- stack.push(this.context.model.rootNode);
621
-
622
- while (stack.length > 0) {
623
- const topNode = stack.pop();
624
-
625
- if (topNode.container.containerElement === containerElement)
626
- return topNode;
627
- [].push.apply(stack, topNode.children);
628
- }
629
-
630
- return null;
631
- }
632
-
633
- addLayoutListener(listener: ILayoutEventListener) {
634
- this.layoutEventListeners.push(listener);
635
- }
636
-
637
- removeLayoutListener(listener: ILayoutEventListener) {
638
- this.layoutEventListeners.splice(this.layoutEventListeners.indexOf(listener), 1);
639
- }
640
-
641
- suspendLayout(panel: IDockContainer) {
642
- this.layoutEventListeners.forEach((listener) => {
643
- if (listener.onSuspendLayout) listener.onSuspendLayout(this, panel);
644
- });
645
- }
646
-
647
- resumeLayout(panel: IDockContainer) {
648
- this.layoutEventListeners.forEach((listener) => {
649
- if (listener.onResumeLayout) listener.onResumeLayout(this, panel);
650
- });
651
- }
652
-
653
- notifyOnDock(dockNode: DockNode) {
654
- this._checkShowBackgroundContext();
655
- this.layoutEventListeners.forEach((listener) => {
656
- if (listener.onDock) {
657
- listener.onDock(this, dockNode);
658
- dockNode.container.resize(dockNode.container.width, dockNode.container.height);
659
- }
660
- });
661
- }
662
-
663
- notifyOnTabsReorder(dockNode: DockNode) {
664
- this.layoutEventListeners.forEach((listener) => {
665
- if (listener.onTabsReorder)
666
- listener.onTabsReorder(this, dockNode);
667
- });
668
- }
669
-
670
- notifyOnUnDock(dockNode: DockNode) {
671
- this._checkShowBackgroundContext();
672
- this.layoutEventListeners.forEach((listener) => {
673
- if (listener.onUndock)
674
- listener.onUndock(this, dockNode);
675
- });
676
- }
677
-
678
- notifyOnClosePanel(panel: PanelContainer) {
679
- this._checkShowBackgroundContext();
680
- if (this.activePanel == panel)
681
- this.activePanel = null;
682
- if (this._activeDocument == panel) {
683
- const last = this._activeDocument;
684
- this._activeDocument = null;
685
- this.notifyOnActiveDocumentChange(null, last);
686
- }
687
- this.layoutEventListeners.forEach((listener) => {
688
- if (listener.onClosePanel)
689
- listener.onClosePanel(this, panel);
690
- });
691
- }
692
-
693
- notifyOnCreateDialog(dialog: Dialog) {
694
- this.layoutEventListeners.forEach((listener) => {
695
- if (listener.onCreateDialog)
696
- listener.onCreateDialog(this, dialog);
697
- });
698
- }
699
-
700
- notifyOnHideDialog(dialog: Dialog) {
701
- this.layoutEventListeners.forEach((listener) => {
702
- if (listener.onHideDialog)
703
- listener.onHideDialog(this, dialog);
704
- });
705
- }
706
-
707
-
708
- notifyOnShowDialog(dialog: Dialog) {
709
- this.layoutEventListeners.forEach((listener) => {
710
- if (listener.onShowDialog)
711
- listener.onShowDialog(this, dialog);
712
- });
713
- }
714
-
715
- notifyOnChangeDialogPosition(dialog: Dialog, x: number, y: number) {
716
- this.layoutEventListeners.forEach((listener) => {
717
- if (listener.onChangeDialogPosition)
718
- listener.onChangeDialogPosition(this, dialog, x, y);
719
- });
720
- }
721
-
722
- notifyOnContainerResized(dockContainer: IDockContainer) {
723
- this.layoutEventListeners.forEach((listener) => {
724
- if (listener.onContainerResized)
725
- listener.onContainerResized(this, dockContainer);
726
- });
727
- }
728
-
729
- notifyOnTabChange(tabpage: TabPage) {
730
- this.layoutEventListeners.forEach((listener) => {
731
- if (listener.onTabChanged)
732
- listener.onTabChanged(this, tabpage);
733
- });
734
- }
735
-
736
- notifyOnActivePanelChange(panel: PanelContainer, oldActive: PanelContainer) {
737
- this.layoutEventListeners.forEach((listener) => {
738
- if (listener.onActivePanelChange)
739
- listener.onActivePanelChange(this, panel, oldActive);
740
- });
741
- }
742
-
743
- notifyOnActiveDocumentChange(panel: PanelContainer, oldActive: PanelContainer) {
744
- this.layoutEventListeners.forEach((listener) => {
745
- if (listener.onActiveDocumentChange)
746
- listener.onActiveDocumentChange(this, panel, oldActive);
747
- });
748
- }
749
-
750
- saveState() {
751
- const serializer = new DockGraphSerializer();
752
- return serializer.serialize(this.context.model);
753
- }
754
-
755
- async loadState(json: string) {
756
- const deserializer = new DockGraphDeserializer(this);
757
- this.context.model = await deserializer.deserialize(json);
758
- this.setModel(this.context.model);
759
- }
760
-
761
- getPanels() {
762
- const panels: PanelContainer[] = [];
763
- //all visible nodes
764
- this._allPanels(this.context.model.rootNode, panels);
765
-
766
- //all visible or not dialogs
767
- this.context.model.dialogs.forEach((dialog) => {
768
- //TODO: check visible
769
- panels.push(dialog.panel);
770
- });
771
-
772
- return panels;
773
- }
774
-
775
- undockEnabled(state: boolean) {
776
- this._undockEnabled = state;
777
- this.getPanels().forEach((panel) => {
778
- panel.canUndock(state);
779
- });
780
- }
781
-
782
- lockDockState(state: boolean) {
783
- this.undockEnabled(!state); // false - not enabled
784
- this.hideCloseButton(state); //true - hide
785
- }
786
-
787
- hideCloseButton(state: boolean) {
788
- this.getPanels().forEach((panel) => {
789
- panel.hideCloseButton(state);
790
- });
791
- }
792
-
793
- updatePanels(ids: string[]) {
794
- const panels: PanelContainer[] = [];
795
- //all visible nodes
796
- this._allPanels(this.context.model.rootNode, panels);
797
- //only remove
798
- panels.forEach((panel) => {
799
- if (!Utils.arrayContains(ids, panel.elementContent.id))
800
- panel.close();
801
- });
802
-
803
- this.context.model.dialogs.forEach((dialog) => {
804
- if (Utils.arrayContains(ids, dialog.panel.elementContent.id))
805
- dialog.show();
806
-
807
- else
808
- dialog.hide();
809
- });
810
- return panels;
811
- }
812
-
813
- getVisiblePanels(): PanelContainer[] {
814
- const panels: PanelContainer[] = [];
815
- //all visible nodes
816
- this._allPanels(this.context.model.rootNode, panels);
817
-
818
- //all visible
819
- this.context.model.dialogs.forEach((dialog) => {
820
- if (!dialog.isHidden)
821
- panels.push(dialog.panel);
822
- });
823
-
824
- return panels;
825
- }
826
-
827
- _allPanels(node: DockNode, panels: PanelContainer[]) {
828
- node.children.forEach((child) => {
829
- this._allPanels(child, panels);
830
- });
831
- if (node.container.containerType === 'panel')
832
- panels.push(node.container as PanelContainer);
833
- }
834
-
835
- get activeDocument(): PanelContainer {
836
- return this._activeDocument;
837
- }
838
-
839
- get activePanel(): PanelContainer {
840
- return this._activePanel;
841
- }
842
- set activePanel(value: PanelContainer) {
843
- if (value !== this._activePanel) {
844
- if (value && !value.isDialog) //todo store compliete list of panels, remove the closed ones and switch back focus
845
- this._lastPanelNotADialog = value;
846
- if (this._lastPanelNotADialog && this.getPanels().indexOf(this._lastPanelNotADialog) < 0)
847
- this._lastPanelNotADialog = null;
848
- const oldActive = this.activePanel;
849
- if (this.activePanel) {
850
- this.activePanel.elementTitle.classList.remove('dockspan-panel-active');
851
- this.activePanel.elementTitleText.classList.remove('dockspan-panel-titlebar-text-active');
852
- if (this.activePanel.tabPage)
853
- this.activePanel.tabPage.host.setActive(false);
854
- }
855
- this._activePanel = value;
856
- const lastActiveDocument = this._activeDocument;
857
- if (value && value.panelType == PanelType.document)
858
- this._activeDocument = value;
859
-
860
-
861
- if (!value && oldActive && oldActive.isDialog && value == null && this._lastPanelNotADialog && this.activePanel != this._lastPanelNotADialog) {
862
- value = this._lastPanelNotADialog;
863
- this._lastPanelNotADialog = undefined;
864
- }
865
-
866
- this.notifyOnActivePanelChange(value, oldActive);
867
- if (lastActiveDocument != this._activeDocument)
868
- this.notifyOnActiveDocumentChange(this._activeDocument, lastActiveDocument);
869
-
870
- if (value) {
871
- value.elementTitle.classList.add('dockspan-panel-active');
872
- value.elementTitleText.classList.add('dockspan-panel-titlebar-text-active');
873
- if (value.tabPage)
874
- value.tabPage.host.setActive(true);
875
- }
876
- } else {
877
- if (value && value.tabPage)
878
- value.tabPage.host.setActive(true);
879
- }
880
- }
855
+ }
856
+
857
+ get activeDocument(): PanelContainer {
858
+ return this._activeDocument;
859
+ }
860
+
861
+ get activePanel(): PanelContainer {
862
+ return this._activePanel;
863
+ }
864
+ set activePanel(value: PanelContainer) {
865
+ if (value !== this._activePanel) {
866
+ if (value && !value.isDialog) //todo store compliete list of panels, remove the closed ones and switch back focus
867
+ this._lastPanelNotADialog = value;
868
+ if (this._lastPanelNotADialog && this.getPanels().indexOf(this._lastPanelNotADialog) < 0)
869
+ this._lastPanelNotADialog = null;
870
+ let oldActive = this.activePanel;
871
+ if (this.activePanel) {
872
+ this.activePanel.elementTitle.classList.remove("dockspan-panel-active");
873
+ this.activePanel.elementTitleText.classList.remove("dockspan-panel-titlebar-text-active");
874
+ if (this.activePanel.tabPage) {
875
+ this.activePanel.tabPage.host.setActive(false);
876
+ }
877
+ }
878
+ this._activePanel = value;
879
+ let lastActiveDocument = this._activeDocument;
880
+ if (value && value.panelType == PanelType.document) {
881
+ this._activeDocument = value;
882
+ }
883
+
884
+ if (!value && oldActive && oldActive.isDialog && value == null && this._lastPanelNotADialog && this.activePanel != this._lastPanelNotADialog) {
885
+ value = this._lastPanelNotADialog;
886
+ this._lastPanelNotADialog = undefined;
887
+ }
888
+
889
+ this.notifyOnActivePanelChange(value, oldActive);
890
+ if (lastActiveDocument != this._activeDocument) {
891
+ this.notifyOnActiveDocumentChange(this._activeDocument, lastActiveDocument);
892
+ }
893
+ if (value) {
894
+ value.elementTitle.classList.add("dockspan-panel-active");
895
+ value.elementTitleText.classList.add("dockspan-panel-titlebar-text-active");
896
+ if (value.tabPage) {
897
+ value.tabPage.host.setActive(true);
898
+ }
899
+ }
900
+ }
901
+ else {
902
+ if (value && value.tabPage) {
903
+ value.tabPage.host.setActive(true);
904
+ }
905
+ }
906
+ }
881
907
  }