@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,880 @@
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';
22
+
23
+ /**
24
+ * Dock manager manages all the dock panels in a hierarchy, similar to visual studio.
25
+ * It owns a Html Div element inside which all panels are docked
26
+ * Initially the document manager takes up the central space and acts as the root node
27
+ */
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
+ /**
221
+ * Reset the dock model . This happens when the state is loaded from json
222
+ */
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
+ /**
299
+ * Perform a DFS (DeepFirstSearch) on the dock model's tree to find the
300
+ * deepest level panel (i.e. the top-most non-overlapping panel)
301
+ * that is under the mouse cursor
302
+ * Retuns null if no node is found under this point
303
+ */
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);
451
+ }
452
+ splitter.setRatios(ratios);
453
+ } else
454
+ splitter.setContainerRatio(container, ratio);
455
+ }
456
+
457
+ this.rebuildLayout(this.context.model.rootNode);
458
+ this.invalidate();
459
+
460
+ this._checkShowBackgroundContext();
461
+
462
+ return newNode;
463
+ }
464
+
465
+ _requestTabReorder(container: IDockContainer, e) {
466
+ const node = this._findNodeFromContainer(container);
467
+ this.layoutEngine.reorderTabs(node, e.handle, e.state, e.index);
468
+ }
469
+
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);
477
+
478
+ const panelContainer = (<PanelContainer>node.container);
479
+ panelContainer.elementPanel.style.display = 'block';
480
+
481
+ // Create a new dialog window for the undocked panel
482
+ const dialog = new Dialog(panelContainer, this, null);
483
+
484
+ if (panelContainer.lastDialogSize)
485
+ dialog.resize(panelContainer.lastDialogSize.width, panelContainer.lastDialogSize.height);
486
+
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);
496
+ }
497
+ return dialog;
498
+ }
499
+
500
+ /**
501
+ * closes a Panel
502
+ */
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
+ /**
516
+ * Opens a Element in a Dialog
517
+ * It is assumed that only leaf nodes (panels) can be undocked
518
+ */
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
537
+ * It is assumed that only leaf nodes (panels) can be undocked
538
+ */
539
+ requestUndock(container: PanelContainer) {
540
+ const node = this._findNodeFromContainer(container);
541
+ this.layoutEngine.undock(node);
542
+ }
543
+
544
+ /**
545
+ * Removes a dock container from the dock layout hierarcy
546
+ * Returns the node that was removed from the dock tree
547
+ */
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;
570
+ }
571
+ }
572
+
573
+ [].push.apply(stack, topNode.children);
574
+ }
575
+
576
+ return null;
577
+ }
578
+
579
+ getNodeByElement(element: Element): DockNode {
580
+ const stack = [];
581
+ stack.push(this.context.model.rootNode);
582
+
583
+ while (stack.length > 0) {
584
+ const topNode = stack.pop();
585
+
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;
592
+ }
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
+ if (topNode.container === container)
610
+ return topNode;
611
+ [].push.apply(stack, topNode.children);
612
+ }
613
+
614
+ return null;
615
+ }
616
+
617
+ findNodeFromContainerElement(containerElement: HTMLElement) {
618
+ const stack: DockNode[] = [];
619
+ stack.push(this.context.model.rootNode);
620
+
621
+ while (stack.length > 0) {
622
+ const topNode = stack.pop();
623
+
624
+ if (topNode.container.containerElement === containerElement)
625
+ return topNode;
626
+ [].push.apply(stack, topNode.children);
627
+ }
628
+
629
+ return null;
630
+ }
631
+
632
+ addLayoutListener(listener: ILayoutEventListener) {
633
+ this.layoutEventListeners.push(listener);
634
+ }
635
+
636
+ removeLayoutListener(listener: ILayoutEventListener) {
637
+ this.layoutEventListeners.splice(this.layoutEventListeners.indexOf(listener), 1);
638
+ }
639
+
640
+ suspendLayout(panel: IDockContainer) {
641
+ this.layoutEventListeners.forEach((listener) => {
642
+ if (listener.onSuspendLayout) listener.onSuspendLayout(this, panel);
643
+ });
644
+ }
645
+
646
+ resumeLayout(panel: IDockContainer) {
647
+ this.layoutEventListeners.forEach((listener) => {
648
+ if (listener.onResumeLayout) listener.onResumeLayout(this, panel);
649
+ });
650
+ }
651
+
652
+ notifyOnDock(dockNode: DockNode) {
653
+ this._checkShowBackgroundContext();
654
+ this.layoutEventListeners.forEach((listener) => {
655
+ if (listener.onDock) {
656
+ listener.onDock(this, dockNode);
657
+ dockNode.container.resize(dockNode.container.width, dockNode.container.height);
658
+ }
659
+ });
660
+ }
661
+
662
+ notifyOnTabsReorder(dockNode: DockNode) {
663
+ this.layoutEventListeners.forEach((listener) => {
664
+ if (listener.onTabsReorder)
665
+ listener.onTabsReorder(this, dockNode);
666
+ });
667
+ }
668
+
669
+ notifyOnUnDock(dockNode: DockNode) {
670
+ this._checkShowBackgroundContext();
671
+ this.layoutEventListeners.forEach((listener) => {
672
+ if (listener.onUndock)
673
+ listener.onUndock(this, dockNode);
674
+ });
675
+ }
676
+
677
+ notifyOnClosePanel(panel: PanelContainer) {
678
+ this._checkShowBackgroundContext();
679
+ if (this.activePanel == panel)
680
+ this.activePanel = null;
681
+ if (this._activeDocument == panel) {
682
+ const last = this._activeDocument;
683
+ this._activeDocument = null;
684
+ this.notifyOnActiveDocumentChange(null, last);
685
+ }
686
+ this.layoutEventListeners.forEach((listener) => {
687
+ if (listener.onClosePanel)
688
+ listener.onClosePanel(this, panel);
689
+ });
690
+ }
691
+
692
+ notifyOnCreateDialog(dialog: Dialog) {
693
+ this.layoutEventListeners.forEach((listener) => {
694
+ if (listener.onCreateDialog)
695
+ listener.onCreateDialog(this, dialog);
696
+ });
697
+ }
698
+
699
+ notifyOnHideDialog(dialog: Dialog) {
700
+ this.layoutEventListeners.forEach((listener) => {
701
+ if (listener.onHideDialog)
702
+ listener.onHideDialog(this, dialog);
703
+ });
704
+ }
705
+
706
+
707
+ notifyOnShowDialog(dialog: Dialog) {
708
+ this.layoutEventListeners.forEach((listener) => {
709
+ if (listener.onShowDialog)
710
+ listener.onShowDialog(this, dialog);
711
+ });
712
+ }
713
+
714
+ notifyOnChangeDialogPosition(dialog: Dialog, x: number, y: number) {
715
+ this.layoutEventListeners.forEach((listener) => {
716
+ if (listener.onChangeDialogPosition)
717
+ listener.onChangeDialogPosition(this, dialog, x, y);
718
+ });
719
+ }
720
+
721
+ notifyOnContainerResized(dockContainer: IDockContainer) {
722
+ this.layoutEventListeners.forEach((listener) => {
723
+ if (listener.onContainerResized)
724
+ listener.onContainerResized(this, dockContainer);
725
+ });
726
+ }
727
+
728
+ notifyOnTabChange(tabpage: TabPage) {
729
+ this.layoutEventListeners.forEach((listener) => {
730
+ if (listener.onTabChanged)
731
+ listener.onTabChanged(this, tabpage);
732
+ });
733
+ }
734
+
735
+ notifyOnActivePanelChange(panel: PanelContainer, oldActive: PanelContainer) {
736
+ this.layoutEventListeners.forEach((listener) => {
737
+ if (listener.onActivePanelChange)
738
+ listener.onActivePanelChange(this, panel, oldActive);
739
+ });
740
+ }
741
+
742
+ notifyOnActiveDocumentChange(panel: PanelContainer, oldActive: PanelContainer) {
743
+ this.layoutEventListeners.forEach((listener) => {
744
+ if (listener.onActiveDocumentChange)
745
+ listener.onActiveDocumentChange(this, panel, oldActive);
746
+ });
747
+ }
748
+
749
+ saveState() {
750
+ const serializer = new DockGraphSerializer();
751
+ return serializer.serialize(this.context.model);
752
+ }
753
+
754
+ async loadState(json: string) {
755
+ const deserializer = new DockGraphDeserializer(this);
756
+ this.context.model = await deserializer.deserialize(json);
757
+ this.setModel(this.context.model);
758
+ }
759
+
760
+ getPanels() {
761
+ const panels: PanelContainer[] = [];
762
+ //all visible nodes
763
+ this._allPanels(this.context.model.rootNode, panels);
764
+
765
+ //all visible or not dialogs
766
+ this.context.model.dialogs.forEach((dialog) => {
767
+ //TODO: check visible
768
+ panels.push(dialog.panel);
769
+ });
770
+
771
+ return panels;
772
+ }
773
+
774
+ undockEnabled(state: boolean) {
775
+ this._undockEnabled = state;
776
+ this.getPanels().forEach((panel) => {
777
+ panel.canUndock(state);
778
+ });
779
+ }
780
+
781
+ lockDockState(state: boolean) {
782
+ this.undockEnabled(!state); // false - not enabled
783
+ this.hideCloseButton(state); //true - hide
784
+ }
785
+
786
+ hideCloseButton(state: boolean) {
787
+ this.getPanels().forEach((panel) => {
788
+ panel.hideCloseButton(state);
789
+ });
790
+ }
791
+
792
+ updatePanels(ids: string[]) {
793
+ const panels: PanelContainer[] = [];
794
+ //all visible nodes
795
+ this._allPanels(this.context.model.rootNode, panels);
796
+ //only remove
797
+ panels.forEach((panel) => {
798
+ if (!Utils.arrayContains(ids, panel.elementContent.id))
799
+ panel.close();
800
+ });
801
+
802
+ this.context.model.dialogs.forEach((dialog) => {
803
+ if (Utils.arrayContains(ids, dialog.panel.elementContent.id))
804
+ dialog.show();
805
+
806
+ else
807
+ dialog.hide();
808
+ });
809
+ return panels;
810
+ }
811
+
812
+ getVisiblePanels(): PanelContainer[] {
813
+ const panels: PanelContainer[] = [];
814
+ //all visible nodes
815
+ this._allPanels(this.context.model.rootNode, panels);
816
+
817
+ //all visible
818
+ this.context.model.dialogs.forEach((dialog) => {
819
+ if (!dialog.isHidden)
820
+ panels.push(dialog.panel);
821
+ });
822
+
823
+ return panels;
824
+ }
825
+
826
+ _allPanels(node: DockNode, panels: PanelContainer[]) {
827
+ node.children.forEach((child) => {
828
+ this._allPanels(child, panels);
829
+ });
830
+ if (node.container.containerType === 'panel')
831
+ panels.push(node.container as PanelContainer);
832
+ }
833
+
834
+ get activeDocument(): PanelContainer {
835
+ return this._activeDocument;
836
+ }
837
+
838
+ get activePanel(): PanelContainer {
839
+ return this._activePanel;
840
+ }
841
+ set activePanel(value: PanelContainer) {
842
+ if (value !== this._activePanel) {
843
+ if (value && !value.isDialog) //todo store compliete list of panels, remove the closed ones and switch back focus
844
+ this._lastPanelNotADialog = value;
845
+ if (this._lastPanelNotADialog && this.getPanels().indexOf(this._lastPanelNotADialog) < 0)
846
+ this._lastPanelNotADialog = null;
847
+ const oldActive = this.activePanel;
848
+ if (this.activePanel) {
849
+ this.activePanel.elementTitle.classList.remove('dockspan-panel-active');
850
+ this.activePanel.elementTitleText.classList.remove('dockspan-panel-titlebar-text-active');
851
+ if (this.activePanel.tabPage)
852
+ this.activePanel.tabPage.host.setActive(false);
853
+ }
854
+ this._activePanel = value;
855
+ const lastActiveDocument = this._activeDocument;
856
+ if (value && value.panelType == PanelType.document)
857
+ this._activeDocument = value;
858
+
859
+
860
+ if (!value && oldActive && oldActive.isDialog && value == null && this._lastPanelNotADialog && this.activePanel != this._lastPanelNotADialog) {
861
+ value = this._lastPanelNotADialog;
862
+ this._lastPanelNotADialog = undefined;
863
+ }
864
+
865
+ this.notifyOnActivePanelChange(value, oldActive);
866
+ if (lastActiveDocument != this._activeDocument)
867
+ this.notifyOnActiveDocumentChange(this._activeDocument, lastActiveDocument);
868
+
869
+ if (value) {
870
+ value.elementTitle.classList.add('dockspan-panel-active');
871
+ value.elementTitleText.classList.add('dockspan-panel-titlebar-text-active');
872
+ if (value.tabPage)
873
+ value.tabPage.host.setActive(true);
874
+ }
875
+ } else {
876
+ if (value && value.tabPage)
877
+ value.tabPage.host.setActive(true);
878
+ }
879
+ }
880
+ }