@finsemble/finsemble-ui 8.0.2 → 8.1.0-beta.2

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 (254) hide show
  1. package/FEA.d.ts +48 -3
  2. package/FEA.d.ts.map +1 -1
  3. package/FEA.js.map +1 -1
  4. package/clients/Interop/FinsembleDesktopAgent.js +1 -1
  5. package/clients/Startup/FSBLDesktop.d.ts +2 -14
  6. package/clients/Startup/FSBLDesktop.d.ts.map +1 -1
  7. package/clients/Startup/FSBLDesktop.js +4 -21
  8. package/clients/Startup/FSBLDesktop.js.map +1 -1
  9. package/clients/Startup/types.d.ts +17 -0
  10. package/clients/Startup/types.d.ts.map +1 -1
  11. package/clients/Startup/windowStartup.d.ts.map +1 -1
  12. package/clients/Startup/windowStartup.js +16 -14
  13. package/clients/Startup/windowStartup.js.map +1 -1
  14. package/clients/routerClient.d.ts +2 -169
  15. package/clients/routerClient.d.ts.map +1 -1
  16. package/clients/routerClient.js +4 -7
  17. package/clients/routerClient.js.map +1 -1
  18. package/common/Desktop.d.ts +8 -0
  19. package/common/Desktop.d.ts.map +1 -1
  20. package/common/Desktop.js +23 -0
  21. package/common/Desktop.js.map +1 -1
  22. package/common/FinsembleWindow.d.ts +1 -2
  23. package/common/FinsembleWindow.d.ts.map +1 -1
  24. package/common/FinsembleWindow.js +1 -1
  25. package/common/FinsembleWindow.js.map +1 -1
  26. package/common/Monitors.d.ts +6 -0
  27. package/common/Monitors.d.ts.map +1 -1
  28. package/common/Monitors.js +22 -0
  29. package/common/Monitors.js.map +1 -1
  30. package/common/system.d.ts +1 -1
  31. package/common/system.d.ts.map +1 -1
  32. package/main.d.ts +29 -29
  33. package/package.json +44 -44
  34. package/platform/services/Interop/types.d.ts +1 -0
  35. package/platform/services/Interop/types.d.ts.map +1 -1
  36. package/platform/services/Interop/types.js.map +1 -1
  37. package/platform/services/router/routerTransport.d.ts.map +1 -1
  38. package/platform/services/router/routerTransport.js +5 -7
  39. package/platform/services/router/routerTransport.js.map +1 -1
  40. package/platform/services/router/types.d.ts +214 -0
  41. package/platform/services/router/types.d.ts.map +1 -0
  42. package/platform/services/router/types.js +2 -0
  43. package/platform/services/router/types.js.map +1 -0
  44. package/platform/services/types.d.ts +1 -0
  45. package/platform/services/types.d.ts.map +1 -1
  46. package/platform/services/types.js +1 -0
  47. package/platform/services/types.js.map +1 -1
  48. package/platform/services/window/Common/Pools/ObjectPool.d.ts +11 -0
  49. package/platform/services/window/Common/Pools/ObjectPool.d.ts.map +1 -0
  50. package/platform/services/window/Common/Pools/ObjectPool.js +43 -0
  51. package/platform/services/window/Common/Pools/ObjectPool.js.map +1 -0
  52. package/platform/services/window/Common/Pools/PoolSingletons.d.ts +10 -0
  53. package/platform/services/window/Common/Pools/PoolSingletons.d.ts.map +1 -0
  54. package/platform/services/window/Common/Pools/PoolSingletons.js +10 -0
  55. package/platform/services/window/Common/Pools/PoolSingletons.js.map +1 -0
  56. package/platform/services/window/Common/Pools/WindowPool.d.ts +7 -0
  57. package/platform/services/window/Common/Pools/WindowPool.d.ts.map +1 -0
  58. package/platform/services/window/Common/Pools/WindowPool.js +16 -0
  59. package/platform/services/window/Common/Pools/WindowPool.js.map +1 -0
  60. package/platform/services/window/Docking/boxMath.d.ts +144 -0
  61. package/platform/services/window/Docking/boxMath.d.ts.map +1 -0
  62. package/platform/services/window/Docking/boxMath.js +511 -0
  63. package/platform/services/window/Docking/boxMath.js.map +1 -0
  64. package/platform/services/window/Docking/constants.d.ts +29 -0
  65. package/platform/services/window/Docking/constants.d.ts.map +1 -0
  66. package/platform/services/window/Docking/constants.js +29 -0
  67. package/platform/services/window/Docking/constants.js.map +1 -0
  68. package/platform/services/window/Docking/dockableBox.d.ts +117 -0
  69. package/platform/services/window/Docking/dockableBox.d.ts.map +1 -0
  70. package/platform/services/window/Docking/dockableBox.js +525 -0
  71. package/platform/services/window/Docking/dockableBox.js.map +1 -0
  72. package/platform/services/window/Docking/dockableGroup.d.ts +252 -0
  73. package/platform/services/window/Docking/dockableGroup.d.ts.map +1 -0
  74. package/platform/services/window/Docking/dockableGroup.js +1054 -0
  75. package/platform/services/window/Docking/dockableGroup.js.map +1 -0
  76. package/platform/services/window/Docking/dockableMonitor.d.ts +99 -0
  77. package/platform/services/window/Docking/dockableMonitor.d.ts.map +1 -0
  78. package/platform/services/window/Docking/dockableMonitor.js +427 -0
  79. package/platform/services/window/Docking/dockableMonitor.js.map +1 -0
  80. package/platform/services/window/Docking/dockableWindow.d.ts +272 -0
  81. package/platform/services/window/Docking/dockableWindow.d.ts.map +1 -0
  82. package/platform/services/window/Docking/dockableWindow.js +1239 -0
  83. package/platform/services/window/Docking/dockableWindow.js.map +1 -0
  84. package/platform/services/window/Docking/dockingCalculator.d.ts +749 -0
  85. package/platform/services/window/Docking/dockingCalculator.d.ts.map +1 -0
  86. package/platform/services/window/Docking/dockingCalculator.js +3473 -0
  87. package/platform/services/window/Docking/dockingCalculator.js.map +1 -0
  88. package/platform/services/window/Docking/dockingMain.d.ts +349 -0
  89. package/platform/services/window/Docking/dockingMain.d.ts.map +1 -0
  90. package/platform/services/window/Docking/dockingMain.js +2584 -0
  91. package/platform/services/window/Docking/dockingMain.js.map +1 -0
  92. package/platform/services/window/Docking/maskBoundsCalculator.d.ts +28 -0
  93. package/platform/services/window/Docking/maskBoundsCalculator.d.ts.map +1 -0
  94. package/platform/services/window/Docking/maskBoundsCalculator.js +67 -0
  95. package/platform/services/window/Docking/maskBoundsCalculator.js.map +1 -0
  96. package/platform/services/window/Docking/monitorUpdateHandler.d.ts +32 -0
  97. package/platform/services/window/Docking/monitorUpdateHandler.d.ts.map +1 -0
  98. package/platform/services/window/Docking/monitorUpdateHandler.js +117 -0
  99. package/platform/services/window/Docking/monitorUpdateHandler.js.map +1 -0
  100. package/platform/services/window/Docking/types.d.ts +334 -0
  101. package/platform/services/window/Docking/types.d.ts.map +1 -0
  102. package/platform/services/window/Docking/types.js +12 -0
  103. package/platform/services/window/Docking/types.js.map +1 -0
  104. package/platform/services/window/MultiWindowFeatures/autoArrange.d.ts +90 -0
  105. package/platform/services/window/MultiWindowFeatures/autoArrange.d.ts.map +1 -0
  106. package/platform/services/window/MultiWindowFeatures/autoArrange.js +510 -0
  107. package/platform/services/window/MultiWindowFeatures/autoArrange.js.map +1 -0
  108. package/platform/services/window/StackedWindowManager/stackedWindowManager.d.ts +411 -0
  109. package/platform/services/window/StackedWindowManager/stackedWindowManager.d.ts.map +1 -0
  110. package/platform/services/window/StackedWindowManager/stackedWindowManager.js +1641 -0
  111. package/platform/services/window/StackedWindowManager/stackedWindowManager.js.map +1 -0
  112. package/platform/services/window/WindowAbstractions/FinsembleWindowInternal.d.ts +9 -0
  113. package/platform/services/window/WindowAbstractions/FinsembleWindowInternal.d.ts.map +1 -0
  114. package/platform/services/window/WindowAbstractions/FinsembleWindowInternal.js +23 -0
  115. package/platform/services/window/WindowAbstractions/FinsembleWindowInternal.js.map +1 -0
  116. package/platform/services/window/WindowAbstractions/WebWindowWrapper.d.ts +227 -0
  117. package/platform/services/window/WindowAbstractions/WebWindowWrapper.d.ts.map +1 -0
  118. package/platform/services/window/WindowAbstractions/WebWindowWrapper.js +1168 -0
  119. package/platform/services/window/WindowAbstractions/WebWindowWrapper.js.map +1 -0
  120. package/platform/services/window/WindowAbstractions/externalWindowWrapper.d.ts +121 -0
  121. package/platform/services/window/WindowAbstractions/externalWindowWrapper.d.ts.map +1 -0
  122. package/platform/services/window/WindowAbstractions/externalWindowWrapper.js +591 -0
  123. package/platform/services/window/WindowAbstractions/externalWindowWrapper.js.map +1 -0
  124. package/platform/services/window/WindowAbstractions/stackedWindowWrapper.d.ts +194 -0
  125. package/platform/services/window/WindowAbstractions/stackedWindowWrapper.d.ts.map +1 -0
  126. package/platform/services/window/WindowAbstractions/stackedWindowWrapper.js +680 -0
  127. package/platform/services/window/WindowAbstractions/stackedWindowWrapper.js.map +1 -0
  128. package/platform/services/window/types.d.ts +13 -13
  129. package/platform/services/window/windowGroup.d.ts +86 -0
  130. package/platform/services/window/windowGroup.d.ts.map +1 -0
  131. package/platform/services/window/windowGroup.js +323 -0
  132. package/platform/services/window/windowGroup.js.map +1 -0
  133. package/platform/services/workspace/windowStorageManager.d.ts +178 -0
  134. package/platform/services/workspace/windowStorageManager.d.ts.map +1 -0
  135. package/platform/services/workspace/windowStorageManager.js +195 -0
  136. package/platform/services/workspace/windowStorageManager.js.map +1 -0
  137. package/platform/services/workspace/workspaceAdminAPI.d.ts +1 -1
  138. package/platform/services/workspace/workspaceAdminAPI.d.ts.map +1 -1
  139. package/react/actions/smartDesktopDesignerActions.d.ts +2 -0
  140. package/react/actions/smartDesktopDesignerActions.d.ts.map +1 -1
  141. package/react/actions/smartDesktopDesignerActions.js +1 -0
  142. package/react/actions/smartDesktopDesignerActions.js.map +1 -1
  143. package/react/assets/css/download.css +119 -0
  144. package/react/assets/css/userPreferences.css +50 -0
  145. package/react/assets/css/windowTitleBar.css +2 -1
  146. package/react/assets/icons/cancel.svg +15 -0
  147. package/react/assets/icons/gear.svg +9 -0
  148. package/react/assets/icons/pause.svg +15 -0
  149. package/react/assets/icons/resume.svg +17 -0
  150. package/react/assets/img/Finsemble-installation.gif +0 -0
  151. package/react/components/common/Button.d.ts +1 -0
  152. package/react/components/common/Button.d.ts.map +1 -1
  153. package/react/components/common/Button.js.map +1 -1
  154. package/react/components/common/ButtonIcon.d.ts.map +1 -1
  155. package/react/components/common/ButtonIcon.js +3 -2
  156. package/react/components/common/ButtonIcon.js.map +1 -1
  157. package/react/components/common/FinsembleIcon.d.ts +1 -1
  158. package/react/components/common/FinsembleIcon.d.ts.map +1 -1
  159. package/react/components/common/FinsembleIcon.js +8 -0
  160. package/react/components/common/FinsembleIcon.js.map +1 -1
  161. package/react/components/common/css/button.css +8 -2
  162. package/react/components/downloadManager/DownloadItem.d.ts +16 -0
  163. package/react/components/downloadManager/DownloadItem.d.ts.map +1 -0
  164. package/react/components/downloadManager/DownloadItem.js +74 -0
  165. package/react/components/downloadManager/DownloadItem.js.map +1 -0
  166. package/react/components/downloadManager/DownloadManager.d.ts +10 -0
  167. package/react/components/downloadManager/DownloadManager.d.ts.map +1 -0
  168. package/react/components/downloadManager/DownloadManager.js +42 -0
  169. package/react/components/downloadManager/DownloadManager.js.map +1 -0
  170. package/react/components/downloadManager/index.d.ts +2 -0
  171. package/react/components/downloadManager/index.d.ts.map +1 -0
  172. package/react/components/downloadManager/index.js +2 -0
  173. package/react/components/downloadManager/index.js.map +1 -0
  174. package/react/components/fdc3Resolver/ResolverDialog.css +1 -1
  175. package/react/components/index.d.ts +1 -0
  176. package/react/components/index.d.ts.map +1 -1
  177. package/react/components/index.js +1 -0
  178. package/react/components/index.js.map +1 -1
  179. package/react/components/processMonitor/ProcessMonitor.d.ts.map +1 -1
  180. package/react/components/processMonitor/ProcessMonitor.js +56 -75
  181. package/react/components/processMonitor/ProcessMonitor.js.map +1 -1
  182. package/react/components/processMonitor/components/ChildWindow.d.ts +5 -7
  183. package/react/components/processMonitor/components/ChildWindow.d.ts.map +1 -1
  184. package/react/components/processMonitor/components/ChildWindow.js +30 -33
  185. package/react/components/processMonitor/components/ChildWindow.js.map +1 -1
  186. package/react/components/processMonitor/components/ListHeader.d.ts +4 -16
  187. package/react/components/processMonitor/components/ListHeader.d.ts.map +1 -1
  188. package/react/components/processMonitor/components/ListHeader.js +30 -39
  189. package/react/components/processMonitor/components/ListHeader.js.map +1 -1
  190. package/react/components/processMonitor/components/ProcessStatistics.d.ts +3 -6
  191. package/react/components/processMonitor/components/ProcessStatistics.d.ts.map +1 -1
  192. package/react/components/processMonitor/components/ProcessStatistics.js +18 -23
  193. package/react/components/processMonitor/components/ProcessStatistics.js.map +1 -1
  194. package/react/components/sdd/Dashboard.css +21 -0
  195. package/react/components/sdd/css/export.css +33 -3
  196. package/react/components/sdd/css/nav.css +1 -1
  197. package/react/components/shared/DefaultDropdownButton.js +1 -1
  198. package/react/components/shared/DefaultDropdownButton.js.map +1 -1
  199. package/react/components/toolbar/DownloadButton.d.ts +8 -0
  200. package/react/components/toolbar/DownloadButton.d.ts.map +1 -0
  201. package/react/components/toolbar/DownloadButton.js +30 -0
  202. package/react/components/toolbar/DownloadButton.js.map +1 -0
  203. package/react/components/toolbar/advancedAppLauncher/stores/StoreActions.d.ts.map +1 -1
  204. package/react/components/toolbar/advancedAppLauncher/stores/StoreActions.js +6 -0
  205. package/react/components/toolbar/advancedAppLauncher/stores/StoreActions.js.map +1 -1
  206. package/react/components/toolbar/appLauncher/AppLauncherMenu.js +1 -1
  207. package/react/components/toolbar/appLauncher/AppLauncherMenu.js.map +1 -1
  208. package/react/components/toolbar/dashbar/Dashbar.d.ts.map +1 -1
  209. package/react/components/toolbar/dashbar/Dashbar.js +72 -47
  210. package/react/components/toolbar/dashbar/Dashbar.js.map +1 -1
  211. package/react/components/toolbar/dashbar/DashbarItem.d.ts +1 -1
  212. package/react/components/toolbar/dashbar/DashbarItem.d.ts.map +1 -1
  213. package/react/components/toolbar/dashbar/DashbarItem.js +25 -4
  214. package/react/components/toolbar/dashbar/DashbarItem.js.map +1 -1
  215. package/react/components/toolbar/index.d.ts +1 -0
  216. package/react/components/toolbar/index.d.ts.map +1 -1
  217. package/react/components/toolbar/index.js +1 -0
  218. package/react/components/toolbar/index.js.map +1 -1
  219. package/react/components/toolbar/workspaceManagementMenu/components/WorkspaceActions.d.ts +3 -4
  220. package/react/components/toolbar/workspaceManagementMenu/components/WorkspaceActions.d.ts.map +1 -1
  221. package/react/components/toolbar/workspaceManagementMenu/components/WorkspaceActions.js +3 -10
  222. package/react/components/toolbar/workspaceManagementMenu/components/WorkspaceActions.js.map +1 -1
  223. package/react/components/userPreferences/components/content/General.d.ts.map +1 -1
  224. package/react/components/userPreferences/components/content/General.js +3 -0
  225. package/react/components/userPreferences/components/content/General.js.map +1 -1
  226. package/react/components/userPreferences/components/general/DownloadPreferences.d.ts +10 -0
  227. package/react/components/userPreferences/components/general/DownloadPreferences.d.ts.map +1 -0
  228. package/react/components/userPreferences/components/general/DownloadPreferences.js +111 -0
  229. package/react/components/userPreferences/components/general/DownloadPreferences.js.map +1 -0
  230. package/react/components/userPreferences/stores/UserPreferencesStore.d.ts +6 -0
  231. package/react/components/userPreferences/stores/UserPreferencesStore.d.ts.map +1 -1
  232. package/react/components/userPreferences/stores/UserPreferencesStore.js +11 -0
  233. package/react/components/userPreferences/stores/UserPreferencesStore.js.map +1 -1
  234. package/react/components/windowTitleBar/components/right/CloseButton.d.ts +2 -26
  235. package/react/components/windowTitleBar/components/right/CloseButton.d.ts.map +1 -1
  236. package/react/components/windowTitleBar/components/right/CloseButton.js +8 -25
  237. package/react/components/windowTitleBar/components/right/CloseButton.js.map +1 -1
  238. package/react/hooks/useDownloadItems.d.ts +24 -0
  239. package/react/hooks/useDownloadItems.d.ts.map +1 -0
  240. package/react/hooks/useDownloadItems.js +68 -0
  241. package/react/hooks/useDownloadItems.js.map +1 -0
  242. package/react/hooks/useNotifications.d.ts +1 -1
  243. package/react/reducers/rootReducer.d.ts +4 -0
  244. package/react/reducers/rootReducer.d.ts.map +1 -1
  245. package/react/reducers/smartDesktopDesignerReducer.d.ts.map +1 -1
  246. package/react/reducers/smartDesktopDesignerReducer.js +4 -0
  247. package/react/reducers/smartDesktopDesignerReducer.js.map +1 -1
  248. package/react/store.d.ts +8 -0
  249. package/react/store.d.ts.map +1 -1
  250. package/react/types/dashbarTypes.d.ts +3 -1
  251. package/react/types/dashbarTypes.d.ts.map +1 -1
  252. package/react/types/smartDesktopDesignerTypes.d.ts +2 -0
  253. package/react/types/smartDesktopDesignerTypes.d.ts.map +1 -1
  254. package/react/types/smartDesktopDesignerTypes.js.map +1 -1
@@ -0,0 +1,1641 @@
1
+ /*!
2
+ * Copyright 2017 - 2020 by ChartIQ, Inc.
3
+ * All rights reserved.
4
+ */
5
+ // This file contains the service to manage all stacked windows.
6
+ // The common/window/stackedWindow wrapper contains the primary interface. Also, common/StackedWindowManager contains interface to createStackedWindow used by Launcher.
7
+ import { RouterClient } from "../../../../clients/routerClient";
8
+ import { Logger } from "../../../../clients/logger";
9
+ import { FinsembleWindowInternal } from "../WindowAbstractions/FinsembleWindowInternal";
10
+ import { ConfigUtilInstance as ConfigUtil } from "../../../../common/configUtil";
11
+ import * as constants from "../../../../common/constants";
12
+ import { GroupPoolSingleton, MonitorPoolSingleton } from "../Common/Pools/PoolSingletons";
13
+ import { BaseWindow } from "../WindowAbstractions/BaseWindow";
14
+ import { each as asyncEach } from "async";
15
+ import _throttle from "lodash/throttle";
16
+ import BoxMath from "../Docking/boxMath";
17
+ import { getMonitorByBounds } from "../../../../common/Monitors";
18
+ /**
19
+ * Constructor for stackedWindow record -- this is what's saved in the store
20
+ *
21
+ * @param {any} stackedWindowIdentifier
22
+ * @memberof StackedWindowManager
23
+ * @private
24
+ */
25
+ class WindowRecord {
26
+ constructor(stackedWindowIdentifier) {
27
+ this.identifier = stackedWindowIdentifier;
28
+ this.childWindowIdentifiers = [];
29
+ this.visibleWindowIdentifier = null;
30
+ this.bounds = null;
31
+ }
32
+ }
33
+ export class StackedWindowManager {
34
+ constructor(params) {
35
+ this.params = params; // keeps any params that ware passed in
36
+ this.childWindow = {}; // holds the wrapper for each child window
37
+ this.storeCache = {}; // maintains a local cache by window name of what what this service keeps in the global store; stays in sync because only this service writes to store
38
+ this.stackedWindowListeners = {}; // saves handles for listeners so can be removed (indexed by stacked window name)
39
+ this.stackedWindowWrappers = {}; // each stacked window has a wrapper so can invoke saveWindowOptions() to save workspace state
40
+ this.eventHandlerFunction = {}; // holds event handlers functions (needed to remove listeners)
41
+ this.childNameToSID = {}; // mapping from child window name to it parent stackedWindowIdentifier
42
+ /**
43
+ * The following events (and these only) should be propagated from the children to the stack.
44
+ */
45
+ this.childEventsToHandle = [
46
+ "maximized",
47
+ "minimized",
48
+ "restored",
49
+ "shown",
50
+ "hidden",
51
+ "focused",
52
+ "broughtToFront",
53
+ "setBounds",
54
+ "alwaysOnTop",
55
+ "setOpacity",
56
+ "bounds-change-request",
57
+ "bounds-change-end",
58
+ "bounds-changed",
59
+ "system-bounds-changed",
60
+ ];
61
+ this.bindAllFunctions();
62
+ window.StackedWindowManager = this;
63
+ }
64
+ initialize(finsembleConfig, callback = Function.prototype) {
65
+ // addReadyTimeout default should be larger than the router failover time (i.e. when failover goes to cross-domain) -- default fail over time adds up to 6 seconds
66
+ this.addReadyTimeout = ConfigUtil.getDefault(finsembleConfig, "finsembleConfig.stackedWindow.addReadyTimeout", 6500);
67
+ Logger.system.debug(`"StackedWindowManager addReadyTimeout ${this.addReadyTimeout}`);
68
+ this.setupStackedWindowServiceListeners();
69
+ this.listenForWorkspaceChanges();
70
+ callback();
71
+ }
72
+ bindAllFunctions() {
73
+ const self = this;
74
+ for (const name of Object.getOwnPropertyNames(Object.getPrototypeOf(self))) {
75
+ const method = self[name];
76
+ // skip constructor
77
+ if (!(method instanceof Function) || method === StackedWindowManager)
78
+ continue;
79
+ self[name] = self[name].bind(self);
80
+ }
81
+ }
82
+ // When the workspace is changed, we need to create a new queue. Without that, the system will wait until the old queue is complete (when it times out...).
83
+ listenForWorkspaceChanges() {
84
+ // RouterClient.addListener("WorkspaceService.switch", this.onWorkspaceChanging);
85
+ }
86
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87
+ // "Hidden" External Interfaces
88
+ // RouterClient.publish(`Finsemble.parentChange.${windowIdentifier.windowName}`, { type: "Added", stackedWindowIdentifier });
89
+ // RouterClient.publish(`Finsemble.parentChange.${windowIdentifier.windowName}`, { type: "Remove", stackedWindowIdentifier });
90
+ //
91
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93
+ // Utility Functions
94
+ // /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
95
+ /**
96
+ * Return true if the specified window in specified stack is showing
97
+ *
98
+ * @param {any} params
99
+ * @returns
100
+ * @memberof StackedWindowManager
101
+ * @private
102
+ */
103
+ isShowing(params) {
104
+ const { stackedWindowIdentifier, windowIdentifier } = params;
105
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
106
+ //
107
+ return (windowIdentifier &&
108
+ thisStackRecord.visibleWindowIdentifier &&
109
+ windowIdentifier.windowName === thisStackRecord.visibleWindowIdentifier.windowName); // returns true if window is visible in stack
110
+ }
111
+ /**
112
+ * Return true if the specified window name is in the specified stack
113
+ *
114
+ * @param {any} params
115
+ * @returns
116
+ * @memberof StackedWindowManager
117
+ * @private
118
+ */
119
+ ifWindowInStack(params) {
120
+ const { thisStackRecord, windowName } = params;
121
+ let result = false;
122
+ for (let i = 0; i < thisStackRecord.childWindowIdentifiers.length; i++) {
123
+ if (thisStackRecord.childWindowIdentifiers[i].name === windowName) {
124
+ result = true;
125
+ }
126
+ }
127
+ return result; // true if the specified window name is in the stack
128
+ }
129
+ /**
130
+ * Return true if the params indication the wrap operation was invoked directly on the window, as opposed to directly on the childWindow
131
+ *
132
+ * @param {any} params
133
+ * @returns
134
+ * @memberof StackedWindowManager
135
+ * @private
136
+ */
137
+ operatingDirectlyOnStackedWindow(params) {
138
+ let result;
139
+ let { stackedWindowIdentifier, windowIdentifier } = params;
140
+ stackedWindowIdentifier = stackedWindowIdentifier || {};
141
+ if (!windowIdentifier || stackedWindowIdentifier.windowName === windowIdentifier.windowName) {
142
+ result = true; // must be a stacked window
143
+ }
144
+ else {
145
+ result = false; // must be operating on a child of a stacked window
146
+ }
147
+ return result;
148
+ }
149
+ /**
150
+ * Return current monitor for the given window bounds
151
+ * @param windowBounds
152
+ * @returns
153
+ * @private
154
+ */
155
+ getMonitor(windowBounds) {
156
+ var _a;
157
+ const overlaps = [];
158
+ for (const monitor of MonitorPoolSingleton.iterator()) {
159
+ const overlap = BoxMath.getOverlap(windowBounds, ((_a = monitor.rawMonitor) === null || _a === void 0 ? void 0 : _a.monitorRect) || monitor.availableRect);
160
+ overlaps.push({
161
+ monitor,
162
+ overlap,
163
+ });
164
+ }
165
+ // Gets the monitor with the greatest overlap. The reduce function pulls the proper object with the greats overlap value. We return the monitor property of that object.
166
+ return overlaps.reduce((prev, current) => (prev.overlap > current.overlap ? prev : current)).monitor;
167
+ }
168
+ /**
169
+ * Update child windows options on restore event
170
+ * @param stackWindow the parent stacked window
171
+ * @param restoredBounds the bounds after restoring
172
+ * @private
173
+ */
174
+ restoreChildren(stackWindow, restoredBounds) {
175
+ stackWindow.childWindowIdentifiers.forEach((childIdentifier) => {
176
+ const childWindow = this.childWindow[childIdentifier.windowName];
177
+ if (childWindow) {
178
+ childWindow.ignoreSystemRestore = false;
179
+ if (childWindow.windowState !== constants.WINDOWSTATE.NORMAL) {
180
+ childWindow._restore({ invokedByParent: true });
181
+ }
182
+ childWindow._setBounds({ bounds: restoredBounds, invokedByParent: true });
183
+ if (childWindow.name !== stackWindow.visibleWindowIdentifier.windowName) {
184
+ childWindow._hide({ invokedByParent: true });
185
+ }
186
+ }
187
+ });
188
+ }
189
+ /**
190
+ * Update child windows options on maximize event
191
+ * @param stackWindow the parent stacked window
192
+ * @private
193
+ */
194
+ maximizeChildren(stackWindow) {
195
+ const monitor = getMonitorByBounds(stackWindow.bounds);
196
+ stackWindow.childWindowIdentifiers.forEach((childIdentifier) => {
197
+ const childWindow = this.childWindow[childIdentifier.windowName];
198
+ if (childWindow) {
199
+ /**
200
+ * Work around for a bug in which a switching tabs is triggering a system restore that would restore the window to its original size.
201
+ * The ignoreSystemRestore flag is added before childWrapper._show to indicate that we are in a maximized state and *only* switching
202
+ * tabs and therefore we do not want to restore the window.
203
+ */
204
+ childWindow.ignoreSystemRestore = true;
205
+ if (childWindow.windowState !== constants.WINDOWSTATE.MAXIMIZED) {
206
+ childWindow._maximize({ invokedByParent: true });
207
+ }
208
+ childWindow._setBounds({ bounds: monitor.availableRect, invokedByParent: true });
209
+ if (childWindow.name !== stackWindow.visibleWindowIdentifier.windowName) {
210
+ childWindow._hide({ invokedByParent: true });
211
+ }
212
+ }
213
+ });
214
+ }
215
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
216
+ // Setup router listeners to handing incoming service requests and events from child windows
217
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218
+ eventChannelName(stackedWindowName, channelTopic) {
219
+ return `StackedWindow-${stackedWindowName}-${channelTopic}`;
220
+ }
221
+ setupInterfaceListener(methodName, methodFunction) {
222
+ RouterClient.addResponder(`StackedWindow.${methodName}`, (err, queryMessage) => {
223
+ if (err) {
224
+ Logger.system.error(`StackedWindow.${methodName} addResponder failed: ${err}`);
225
+ }
226
+ else {
227
+ if (queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.data.windowIdentifier) {
228
+ // Ensure that the WI has matching windowName and name (in case a client sends the wrong one).
229
+ if (queryMessage.data.windowIdentifier.windowName) {
230
+ queryMessage.data.windowIdentifier.name = queryMessage.data.windowIdentifier.windowName;
231
+ }
232
+ else if (queryMessage.data.windowIdentifier.name) {
233
+ queryMessage.data.windowIdentifier.windowName = queryMessage.data.windowIdentifier.name;
234
+ }
235
+ }
236
+ const callback = (error, response) => {
237
+ queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.sendQueryResponse(error, response);
238
+ };
239
+ methodFunction(queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.data, callback);
240
+ }
241
+ });
242
+ }
243
+ setupStackedWindowServiceListeners() {
244
+ // window wrapper entry points
245
+ this.setupInterfaceListener("minimize", this.minimize);
246
+ this.setupInterfaceListener("maximize", this.maximize);
247
+ this.setupInterfaceListener("restore", this.restore);
248
+ this.setupInterfaceListener("focus", this.focus);
249
+ this.setupInterfaceListener("bringToFront", this.bringToFront);
250
+ this.setupInterfaceListener("saveWindowOptions", this.saveWindowStateToStore);
251
+ this.setupInterfaceListener("setBounds", this.setBounds);
252
+ this.setupInterfaceListener("getBounds", this.getBounds);
253
+ this.setupInterfaceListener("getBoundsFromSystem", this.getBoundsFromSystem);
254
+ this.setupInterfaceListener("startMove", this.startMove);
255
+ this.setupInterfaceListener("stopMove", this.stopMove);
256
+ // this.setupInterfaceListener("updateOptions", this.updateOptions);
257
+ this.setupInterfaceListener("hide", this.hide);
258
+ this.setupInterfaceListener("show", this.show);
259
+ this.setupInterfaceListener("close", this.close);
260
+ this.setupInterfaceListener("reorder", this.reorder);
261
+ this.setupInterfaceListener("alwaysOnTop", this.setAlwaysOnTop);
262
+ // this.setupInterfaceListener("setOpacity", this.setOpacity);
263
+ RouterClient.addResponder("StackedWindow.setOpacity", (err, queryMessage) => {
264
+ if (err) {
265
+ Logger.system.error(`StackedWindow.setOpacity addResponder failed: ${err}`);
266
+ }
267
+ else {
268
+ this.setOpacity(queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.data, (setOpacityError, response) => {
269
+ queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.sendQueryResponse(setOpacityError, response);
270
+ });
271
+ }
272
+ });
273
+ RouterClient.addResponder("StackedWindow.updateOptions", (err, queryMessage) => {
274
+ if (err) {
275
+ Logger.system.error(`StackedWindow.updateOptions addResponder failed: ${err}`);
276
+ }
277
+ else {
278
+ this.updateOptions(queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.data, (updateOptionsError, response) => {
279
+ queryMessage === null || queryMessage === void 0 ? void 0 : queryMessage.sendQueryResponse(updateOptionsError, response);
280
+ });
281
+ }
282
+ });
283
+ }
284
+ async visibleChildEventHandler(stackedWindowName, stackWrap, event) {
285
+ const stackedWindowIdentifier = {
286
+ windowName: stackedWindowName,
287
+ name: stackedWindowName,
288
+ windowType: "StackedWindow",
289
+ };
290
+ const thisStackRecord = this.storeCache[stackedWindowName];
291
+ // Sometimes removal of visible Child events never happens. Not sure why. Under normal circumstances, this is not an issue because you generally don't get here
292
+ // However in the case of evergreen components, this prevents the evergreen component from moving when launched in another workspace.
293
+ // So cleanup listeners if we somehow managed to get here and the stack doesn't exist.
294
+ if (!this.storeCache[stackedWindowName]) {
295
+ const { wrap: childWrap } = await BaseWindow.getInstance({ name: event.source });
296
+ this.removeChildEventListener(stackedWindowName, event.source, childWrap);
297
+ return;
298
+ }
299
+ switch (event.event) {
300
+ case "bounds-change-end":
301
+ this.saveWindowOptions({ closing: false }, stackedWindowIdentifier);
302
+ stackWrap.eventManager.trigger(event.event, event.data);
303
+ Logger.system.verbose("StackedWindowManager transmitting event", event.event, this.eventChannelName(stackedWindowName, event.event), event);
304
+ break;
305
+ case "restored":
306
+ stackWrap.windowState = constants.WINDOWSTATE.NORMAL;
307
+ this.restoreChildren(thisStackRecord, event.data.bounds);
308
+ break;
309
+ case "maximized":
310
+ stackWrap.windowState = constants.WINDOWSTATE.MAXIMIZED;
311
+ this.maximizeChildren(thisStackRecord);
312
+ break;
313
+ case "alwaysOnTop": {
314
+ let alwaysOnTopValue = event.data.alwaysOnTop;
315
+ if (alwaysOnTopValue === undefined) {
316
+ const eventWindowName = event.data.windowName;
317
+ const activeChildWindow = this.childWindow[eventWindowName];
318
+ alwaysOnTopValue = !activeChildWindow.getParent().alwaysOnTop; // gets the parent alwaysOnTop value and toggles it
319
+ }
320
+ await this.setAlwaysOnTop({
321
+ stackedWindowIdentifier,
322
+ alwaysOnTop: alwaysOnTopValue,
323
+ });
324
+ break;
325
+ }
326
+ default:
327
+ stackWrap.eventManager.trigger(event.event, event.data);
328
+ Logger.system.verbose("StackedWindowManager transmitting event", event.eventName, this.eventChannelName(stackedWindowName, event.event), event);
329
+ break;
330
+ }
331
+ }
332
+ addChildEventListener(stackedWindowName, childName, childWrapper) {
333
+ Logger.system.debug("StackedWindowManagerService.addChildEventListener", stackedWindowName, childName);
334
+ FinsembleWindowInternal.getInstance({ name: stackedWindowName }, (err, stackWrap) => {
335
+ for (let i = 0; i < this.childEventsToHandle.length; i++) {
336
+ const eventName = this.childEventsToHandle[i];
337
+ let eventHandler = (eventObject) => {
338
+ this.visibleChildEventHandler(stackedWindowName, stackWrap, eventObject);
339
+ };
340
+ if (eventName === "bounds-change-request") {
341
+ eventHandler = _throttle(eventHandler, 10);
342
+ }
343
+ if (!this.eventHandlerFunction[stackedWindowName])
344
+ this.eventHandlerFunction[stackedWindowName] = {};
345
+ if (this.eventHandlerFunction[stackedWindowName][eventName]) {
346
+ Logger.system.warn("Avoiding Registering the same Listener Twice.");
347
+ }
348
+ else {
349
+ Logger.system.debug("StackedWindowManager addChildEventListener", eventName, childName);
350
+ this.eventHandlerFunction[stackedWindowName][eventName] = eventHandler;
351
+ childWrapper.addEventListener(eventName, eventHandler);
352
+ }
353
+ }
354
+ });
355
+ }
356
+ removeChildEventListener(stackedWindowName, childName, childWrapper) {
357
+ Logger.system.debug("StackedWindowManager.removeChildEventListener", stackedWindowName, childName);
358
+ // We may try to remove listeners before adding them. If so, don't error out.
359
+ if (!this.eventHandlerFunction[stackedWindowName])
360
+ this.eventHandlerFunction[stackedWindowName] = {};
361
+ for (let i = 0; i < this.childEventsToHandle.length; i++) {
362
+ const eventName = this.childEventsToHandle[i];
363
+ const handler = this.eventHandlerFunction[stackedWindowName][eventName];
364
+ if (handler) {
365
+ childWrapper.removeEventListener(eventName, handler);
366
+ delete this.eventHandlerFunction[stackedWindowName][eventName];
367
+ }
368
+ else {
369
+ Logger.system.debug("StackedWindowManager.removeChildEventListener before the listener was added.");
370
+ }
371
+ }
372
+ }
373
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
374
+ // The next section of functions are oriented to managing Stacked Windows throughout the system.
375
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
376
+ // returns true if all the groupWindows are in the array of child windows
377
+ groupWindowsContainedInStacked(groupWindows, childWindows) {
378
+ let matchCount = 0;
379
+ let groupWindowCount = 0;
380
+ let groupWindow;
381
+ for (groupWindow in groupWindows) {
382
+ groupWindowCount++; // count the number of group windows
383
+ if (groupWindows.hasOwnProperty(groupWindow)) {
384
+ for (const childWindow of childWindows) {
385
+ if (groupWindow === childWindow.name) {
386
+ matchCount++; // count the matches found in child windows
387
+ }
388
+ }
389
+ }
390
+ }
391
+ return groupWindowCount === matchCount; // return true if all group windows found in child windows
392
+ }
393
+ // when a new child window is added to the stack, this function determines if the stacked window should join any of the children groups
394
+ joinGroups(groups, stackedWindowIdentifier) {
395
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
396
+ if (!thisStackRecord) {
397
+ Logger.system.error("stackedWindowManager.joinGroups unidentified stacked window", stackedWindowIdentifier);
398
+ }
399
+ else if (groups) {
400
+ for (const group of groups) {
401
+ const oneGroup = GroupPoolSingleton.get(group);
402
+ if (!this.groupWindowsContainedInStacked(oneGroup.windows, thisStackRecord.childWindowIdentifiers)) {
403
+ // if the group exists outside the stacked window, then join the group
404
+ RouterClient.transmit("DockingService.joinGroup", {
405
+ groupName: group,
406
+ name: stackedWindowIdentifier.windowName,
407
+ });
408
+ }
409
+ }
410
+ }
411
+ }
412
+ getGroups(windowIdentifier) {
413
+ const promiseResolver = async (resolve) => {
414
+ RouterClient.query("DockingService.getGroupsForWindow", { name: windowIdentifier.name }, (err, response) => {
415
+ resolve(response.data);
416
+ });
417
+ };
418
+ return new Promise(promiseResolver);
419
+ }
420
+ /**
421
+ * Creates a new StackedWindow, returning its stackWindowIdentifier in the callback. Optionally initializes stack with a set of child windows.
422
+ *
423
+ * Invoked by Launcher Service when spawning a stacked window (e.g. LauncherClient.spawn()).
424
+ *
425
+ * @param {object} params Parameters
426
+ * @param {array=} params.windowIdentifiers array of windowIdentifiers to add to stack on creation.
427
+ * @param {boolean=} params.new if true then stacked window being defined for first time with no persistent state
428
+ * @param {function=} callback function(err, stackedWindowIdentifier)
429
+ * @memberof StackedWindowManager
430
+ * @private
431
+ */
432
+ async createStackedWindow(params, callback = null) {
433
+ var _a, _b;
434
+ Logger.system.debug("StackedWindowManager.createStackedWindow", params);
435
+ if (params.customData)
436
+ params.customData.manifest = {};
437
+ const stackedWindowIdentifier = {
438
+ windowType: "StackedWindow",
439
+ windowName: params.windowName || params.name,
440
+ };
441
+ let thisStackRecord;
442
+ let subscribeID = null;
443
+ // TABBING TBD: need to finish before callback -- async
444
+ // if (true || params.new) { // being created for the first time (not from workspace with persistent state)
445
+ thisStackRecord = new WindowRecord(stackedWindowIdentifier); // blank initial record
446
+ Object.assign(thisStackRecord, params); // merge windowDescriptor into stackRecord
447
+ thisStackRecord.registeredWithDockingManager = false;
448
+ const windowIdentifiers = thisStackRecord.childWindowIdentifiers && thisStackRecord.childWindowIdentifiers.length
449
+ ? thisStackRecord.childWindowIdentifiers
450
+ : (_b = (_a = thisStackRecord.customData) === null || _a === void 0 ? void 0 : _a.spawnData) === null || _b === void 0 ? void 0 : _b.windowIdentifiers;
451
+ thisStackRecord.childWindowIdentifiers = [];
452
+ // below commented out because don't want to save until complete state
453
+ // this.saveStore(stackedWindowIdentifier); // go ahead and save initial information before waiting on children
454
+ const wrapReadyCallback = async (err, response) => {
455
+ if (response.data && response.data.state === "open") {
456
+ RouterClient.unsubscribe(subscribeID); // no longer need subscription
457
+ for (let i = 0; i < windowIdentifiers.length; i++) {
458
+ const p = Object.assign({}, params);
459
+ p.windowIdentifier = windowIdentifiers[i];
460
+ if (i === 0) {
461
+ p.inheritGroups = true;
462
+ }
463
+ await this.addWindow(p);
464
+ }
465
+ // if not a newStack (i.e. spawned by workspace) the register here after children are added; otherwise for new stacks must dynamically register in addWindow. TBD: need better model here
466
+ if (!params.newStack) {
467
+ await this.registerWithDockingManager({
468
+ windowIdentifier: stackedWindowIdentifier,
469
+ });
470
+ }
471
+ Logger.system.debug("StackedWindowManager.createStackedWindow all available windows added");
472
+ const isVisible = thisStackRecord.visibleWindowIdentifier &&
473
+ thisStackRecord.childWindowIdentifiers.length &&
474
+ !this.ifWindowInStack({
475
+ thisStackRecord,
476
+ windowName: thisStackRecord.visibleWindowIdentifier.windowName,
477
+ });
478
+ // if there is a visible window but the corresponding child window never became ready (for any reason) then set a new visible window
479
+ if (isVisible) {
480
+ Logger.system.error("StackedWindowManager.createStackedWindow resetting visible window to first child since previous visible window couldn't be added");
481
+ this.setVisibleWindow({
482
+ stackedWindowIdentifier,
483
+ windowIdentifier: thisStackRecord.childWindowIdentifiers[0],
484
+ }); // make the first window visible by default
485
+ }
486
+ if (!thisStackRecord.childWindowIdentifiers.length) {
487
+ // TBD: this should essentially mean the stacked-window creation failed, but this has side-effect so just put out error for now. Revisit on cleanup. But tested and roughly handled okay.
488
+ Logger.system.error("StackedWindowManager.createStackedWindow: no children became ready");
489
+ }
490
+ // send notification to LauncherClient that the window has been created (otherwise LauncherClient hangs)
491
+ RouterClient.publish(`Finsemble.${stackedWindowIdentifier.windowName}.componentReady`, {
492
+ name: stackedWindowIdentifier.windowName,
493
+ });
494
+ // note the LauncherService will add to the workspace after spawn completes (spawn is the main client of this function)
495
+ await this.saveWindowOptions({ closing: false }, stackedWindowIdentifier); // save again now children added
496
+ this.setVisibleWindow({
497
+ stackedWindowIdentifier,
498
+ windowIdentifier: thisStackRecord.visibleWindowIdentifier,
499
+ });
500
+ }
501
+ };
502
+ Logger.system.debug("StackedWindowManager.createStackedWindow NewRecord", thisStackRecord);
503
+ this.storeCache[stackedWindowIdentifier.windowName] = thisStackRecord; // cache the stacked window data
504
+ if (windowIdentifiers) {
505
+ // if a list of initial windows provides, then now add them as children
506
+ params.noSave = true; // input to addWindow -- don't save in add because will do it once here after all added
507
+ params.stackedWindowIdentifier = stackedWindowIdentifier;
508
+ // wait for the wrap to be available before adding windows.
509
+ const wrapReadyChannel = `Finsemble.${stackedWindowIdentifier.windowName}.wrapReady`;
510
+ subscribeID = RouterClient.subscribe(wrapReadyChannel, wrapReadyCallback);
511
+ callback === null || callback === void 0 ? void 0 : callback(null, stackedWindowIdentifier);
512
+ }
513
+ }
514
+ /**
515
+ * Private utility function to sleep/wait for a specified time before accepting the returned promise.
516
+ * @private
517
+ */
518
+ sleep(milliseconds) {
519
+ return new Promise((resolve) => setTimeout(() => {
520
+ resolve("Timeout");
521
+ }, milliseconds));
522
+ }
523
+ waitForWrapReady(windowName) {
524
+ const channel = `Finsemble.${windowName}.wrapReady`;
525
+ return new Promise((resolve) => {
526
+ const subscribeID = RouterClient.subscribe(channel, async (err, response) => {
527
+ var _a, _b;
528
+ RouterClient.unsubscribe(subscribeID);
529
+ const available = ((_a = response.data) === null || _a === void 0 ? void 0 : _a.name) === windowName && ((_b = response.data) === null || _b === void 0 ? void 0 : _b.state) === "open";
530
+ if (!available) {
531
+ Logger.system.debug("StackedWindowManager.addWindow waiting", windowName);
532
+ return;
533
+ }
534
+ resolve(null);
535
+ });
536
+ });
537
+ }
538
+ /**
539
+ * Adds window as a child to a stacked window. Adds to the top of the stack, or if specified to a specific location in the stack;
540
+ *
541
+ * @param {object=} params Parameters
542
+ * @param {object} params.stackedWindowIdentifier stacked window to operate on stacked window to operate on
543
+ * @param {object} params.windowIdentifier window to add
544
+ * @param {number=} params.position the location in the stack to push the window. Location 0 is the bottom of the stack. Defaults to the top of stack.
545
+ * @param {boolean=} params.noSave if true then don't save the store after updating it (will be saved by caller)
546
+ * @param {boolean=} params.ignorePreviousState if true then ignore the previous state of the window being added (with in another stack and registered with docking handled elsewhere)
547
+ * @param {boolean=} params.noVisibility if true don't automatically set visibility when first window added to the stack (needed for ordered startup)
548
+ * @param {function=} callback function(err)
549
+ * @memberof StackedWindowManager
550
+ * @private
551
+ */
552
+ async addWindow(params) {
553
+ Logger.system.debug("StackedWindowManager.addWindow", params);
554
+ const { windowName } = params.windowIdentifier;
555
+ // this handles when a window being added never reaches the ready state -- set timer to catch these cases and reject on timeout
556
+ const err = await Promise.race([this.sleep(this.addReadyTimeout), this.waitForWrapReady(windowName)]);
557
+ if (err) {
558
+ const error = `StackedWindowManager.addWindow() child ${params.windowIdentifier.windowName} never became ready`;
559
+ Logger.system.error(error);
560
+ return { err: error };
561
+ }
562
+ Logger.system.debug("StackedWindowManager.addWindow() continuing", params.windowIdentifier.windowName);
563
+ const { stackedWindowIdentifier, windowIdentifier, noSave } = params;
564
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
565
+ if (!thisStackRecord) {
566
+ const error = "StackedWindowManager.addWindow() unknown stackedWindowIdentifier";
567
+ Logger.system.error(error);
568
+ return { err: error };
569
+ }
570
+ // position to add the window
571
+ const { position = thisStackRecord.childWindowIdentifiers.length } = params;
572
+ thisStackRecord.childWindowIdentifiers.splice(position, 0, windowIdentifier); // add to the child array
573
+ this.childNameToSID[windowIdentifier.windowName] = stackedWindowIdentifier; // add mapping to parent stackedWindowIdentifier
574
+ const { data: wrappedWindow } = await FinsembleWindowInternal.getInstanceStandardized(windowIdentifier);
575
+ if (!wrappedWindow) {
576
+ const error = `StackedWindowManager.addWindow() Cannot get wrap for ${windowName}`;
577
+ Logger.system.error(error);
578
+ return { err: error };
579
+ }
580
+ this.childWindow[windowIdentifier.windowName] = wrappedWindow; // save the wrapper for quick use
581
+ // save alwaysOnTop state so that when the window leaves the stack, its original alwaysOnTop state is restored
582
+ if (typeof windowIdentifier.alwaysOnTop !== "boolean")
583
+ windowIdentifier.alwaysOnTop = wrappedWindow._isAlwaysOnTop();
584
+ // if stacked window doesn't have a visible window, then make this window being added the visible window
585
+ if (!thisStackRecord.visibleWindowIdentifier) {
586
+ const { err: err2, data: bounds } = await wrappedWindow._getBounds({}, () => { });
587
+ if (err2 || !bounds) {
588
+ const error = `StackedWindowManager.addWindow() no bounds received ${err2}`;
589
+ Logger.system.error(error);
590
+ return { err: error };
591
+ }
592
+ // get the window bounds and save as the stackedWindow bounds
593
+ Logger.system.debug("StackedWindowManager.addWindow() got bounds", windowIdentifier, bounds);
594
+ this.mergeBounds(thisStackRecord, bounds);
595
+ thisStackRecord.bounds = bounds;
596
+ Object.assign(thisStackRecord, bounds);
597
+ this.setVisibleWindow({
598
+ stackedWindowIdentifier,
599
+ windowIdentifier,
600
+ noSave: params.noSave,
601
+ isAddingChildren: true,
602
+ });
603
+ // if stacked window has a predefined visibleWindow and it matches the window being added, then set this window to the visible window
604
+ }
605
+ else if (thisStackRecord.visibleWindowIdentifier &&
606
+ thisStackRecord.visibleWindowIdentifier.windowName === windowIdentifier.windowName) {
607
+ this.setVisibleWindow({
608
+ stackedWindowIdentifier,
609
+ windowIdentifier,
610
+ noSave: params.noSave,
611
+ isAddingChildren: true,
612
+ });
613
+ // if stacked window has a predefined visibleWindow and it does not match the window being added, then hide this window
614
+ }
615
+ else {
616
+ Logger.system.debug("StackedWindowManager.addWindow hiding window", windowIdentifier);
617
+ // hide the window being added and set it bounds
618
+ wrappedWindow._hide({ invokedByParent: true }, () => {
619
+ Logger.system.debug("StackedWindowManager.addWindow setting bounds", windowIdentifier, thisStackRecord.bounds);
620
+ wrappedWindow._setBounds({
621
+ bounds: thisStackRecord.bounds,
622
+ invokedByParent: true,
623
+ });
624
+ });
625
+ }
626
+ // If the stack is maximized and we're adding a window to it,
627
+ // call to maximize the window
628
+ const { wrap: stackedWrapper } = await BaseWindow.getInstance(stackedWindowIdentifier);
629
+ const childWindow = this.childWindow[windowIdentifier.windowName];
630
+ if (stackedWrapper.windowState === constants.WINDOWSTATE.MAXIMIZED) {
631
+ childWindow._maximize();
632
+ }
633
+ else if (stackedWrapper.windowState === constants.WINDOWSTATE.NORMAL) {
634
+ childWindow._restore();
635
+ }
636
+ if (!params.noRemove) {
637
+ // if higher level (e.g. presentation components) isn't handling the previous state of the window
638
+ // handling the previous state of the window being added
639
+ const { parentWindow } = wrappedWindow;
640
+ if (parentWindow && parentWindow.name != thisStackRecord.name) {
641
+ // if the window being added was already in a stackedWindow, remove it from that stacked window (the window is already unregistered with docking)
642
+ Logger.system.debug("StackedWindowManager.addWindow removing from previous parentWindow", parentWindow.identifier);
643
+ // if adding a window to this stack that needs to be removed from another stack,
644
+ // then when removing don't automatically make the window visible; instead use normally visibility settings in new stacked window
645
+ await this.removeWindow({
646
+ stackedWindowIdentifier: parentWindow.identifier,
647
+ windowIdentifier,
648
+ noVisible: true,
649
+ noDocking: true,
650
+ });
651
+ }
652
+ else {
653
+ // else window is standalone and registered with docking, so deregister with docking (since only stacked window is registered)
654
+ Logger.system.debug("StackedWindowManager.addWindow unregistering from docking (case 1)", windowIdentifier);
655
+ if (params.inheritGroups && params.newStack) {
656
+ await this.registerWithDockingManager({
657
+ windowIdentifier: stackedWindowIdentifier,
658
+ });
659
+ const groups = await this.getGroups(windowIdentifier);
660
+ this.joinGroups(groups, stackedWindowIdentifier);
661
+ }
662
+ this.deregisterWithDockingManager({ windowIdentifier }); // docking manager manage the parentWindow stacked window (not the individual children)
663
+ }
664
+ }
665
+ if (!noSave) {
666
+ await this.saveWindowOptions({ closing: false }, stackedWindowIdentifier); // update the cache and the global store
667
+ }
668
+ // Notify interested listeners (e.g. BaseWindow wrappers for added window) that window was added to the stack
669
+ Logger.system.debug("StackedWindowManager publish parent notification", windowIdentifier.windowName);
670
+ RouterClient.publish(`Finsemble.parentChange.${windowIdentifier.windowName}`, {
671
+ type: "Added",
672
+ stackedWindowIdentifier,
673
+ });
674
+ // Publish Exists event right after the Added event because windows use this event type to track parent state.
675
+ RouterClient.publish(`Finsemble.parentChange.${windowIdentifier.windowName}`, {
676
+ type: "Exists",
677
+ stackedWindowIdentifier,
678
+ });
679
+ await this.makeStackAlwaysOnTopIfNeeded({
680
+ stackedWindowIdentifier,
681
+ });
682
+ return {};
683
+ }
684
+ /**
685
+ * This will make a stack always on top if any child is always on top.
686
+ */
687
+ async makeStackAlwaysOnTopIfNeeded(params) {
688
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
689
+ const alwaysOnTop = thisStackRecord.childWindowIdentifiers.some(({ windowName }) => this.childWindow[windowName]._isAlwaysOnTop());
690
+ if (alwaysOnTop) {
691
+ await this.setAlwaysOnTop({
692
+ stackedWindowIdentifier: params.stackedWindowIdentifier,
693
+ alwaysOnTop: alwaysOnTop,
694
+ });
695
+ }
696
+ }
697
+ triggerEvent(params, cb) {
698
+ FinsembleWindowInternal.getInstance({ stackedWindowManager: this, name: params.windowIdentifier.windowName }, (_err, wrap) => {
699
+ wrap.eventManager.trigger(params.event);
700
+ cb();
701
+ });
702
+ }
703
+ /**
704
+ * Closes and deletes a stacked window. If specified (see params) then children will be closed; otherwise children will be signals they are removed from the stacked window.
705
+ *
706
+ * @param {object} params Parameters
707
+ * @param {object} params.stackedWindowIdentifier stacked window to operate on
708
+ * @param {object=} params.closeChildren if true then also close all children
709
+ * @param {object=} params.removeFromWorkspace if then remove stacked window and child windows from the workspace
710
+ * @param {boolean=} params.waitChildClose if true then wait for child wrapper to close before returned (needed for cleanly switching workspaces)
711
+ * @param {boolean=} params.noDocking if true then do not register removed window with docking (the workspace is unaffected)
712
+ * @param {any} callback
713
+ * @memberof StackedWindowManager
714
+ */
715
+ closeStackedWindow(params, callback = Function.prototype) {
716
+ Logger.system.debug("StackedWindowManager.closeStackedWindow", params.stackedWindowIdentifier.windowName, params);
717
+ const promiseResolver = async (resolve) => {
718
+ let { stackedWindowIdentifier, removeFromWorkspace, closeChildren } = params;
719
+ if (!closeChildren && closeChildren !== false) {
720
+ closeChildren = removeFromWorkspace;
721
+ }
722
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
723
+ Logger.system.debug("StackedWindowManager.closeStackedWindow saveStore done", params.stackedWindowIdentifier.windowName);
724
+ if (!thisStackRecord) {
725
+ const err = "StackedWindowManager.closeStackedWindow: no stacked record";
726
+ Logger.system.error(err, params);
727
+ resolve({ err });
728
+ callback(err);
729
+ }
730
+ else {
731
+ // clear the pubsub state for the stacked window -- must set to empty (to match LaucherClient check)
732
+ RouterClient.publish(`Finsemble.${stackedWindowIdentifier.windowName}.componentReady`, {});
733
+ if (removeFromWorkspace) {
734
+ if (closeChildren) {
735
+ while (thisStackRecord.childWindowIdentifiers.length > 0) {
736
+ // the currently visible window is closed one at a time to support orderly close, which might require UI interaction
737
+ await this.deleteWindow({
738
+ noCloseStack: true,
739
+ waitChildClose: params.waitChildClose,
740
+ stackedWindowIdentifier,
741
+ windowIdentifier: thisStackRecord.visibleWindowIdentifier,
742
+ removeFromWorkspace,
743
+ fromSystem: params.fromSystem,
744
+ });
745
+ }
746
+ }
747
+ else {
748
+ while (thisStackRecord.childWindowIdentifiers.length > 0) {
749
+ await this.removeWindow({
750
+ noCloseStack: true,
751
+ waitChildClose: params.waitChildClose,
752
+ stackedWindowIdentifier,
753
+ windowIdentifier: thisStackRecord.visibleWindowIdentifier,
754
+ });
755
+ }
756
+ }
757
+ this.deregisterWithDockingManager({
758
+ windowIdentifier: stackedWindowIdentifier,
759
+ removeFromWorkspace,
760
+ });
761
+ delete this.storeCache[stackedWindowIdentifier.windowName]; // remove stacked window from cache
762
+ resolve();
763
+ callback();
764
+ }
765
+ else {
766
+ // clear the pubsub parent state for each child window (if not done, children will for some cases incorrectly have a parent specified);
767
+ // note removeWindow() will also clear this parent state, but this path doesn't invoke removeWindow
768
+ for (let i = 0; i < thisStackRecord.childWindowIdentifiers.length; i++) {
769
+ const childName = thisStackRecord.childWindowIdentifiers[i].name;
770
+ Logger.system.debug("StackedWindowManager.closeStackedWindow cleaning up parent state for child", childName);
771
+ RouterClient.publish(`Finsemble.parentChange.${childName}`, {});
772
+ }
773
+ // essentially shouldn't have to do anything else but cleanup local state -- workspace is closing children individually
774
+ if (thisStackRecord.visibleWindowIdentifier) {
775
+ const visibleChildWrapper = this.childWindow[thisStackRecord.visibleWindowIdentifier.windowName];
776
+ this.removeChildEventListener(stackedWindowIdentifier.windowName, thisStackRecord.visibleWindowIdentifier.windowName, visibleChildWrapper);
777
+ }
778
+ delete this.storeCache[stackedWindowIdentifier.windowName]; // remove stacked window from cache
779
+ resolve();
780
+ callback();
781
+ }
782
+ }
783
+ };
784
+ return new Promise(promiseResolver);
785
+ }
786
+ waitForWindowClosed(windowName) {
787
+ return new Promise((resolve) => {
788
+ const subscribeID = RouterClient.subscribe(`Finsemble.${windowName}.wrapReady`, (subscribeError, response) => {
789
+ const { data } = response;
790
+ const windowWasClosed = data.name === windowName && data.state === "closed";
791
+ if (!windowWasClosed) {
792
+ Logger.system.debug("StackedWindowManager.removeWindow waiting", windowName);
793
+ }
794
+ else {
795
+ Logger.system.debug("StackedWindowManager.removeWindow continuing", windowName);
796
+ RouterClient.unsubscribe(subscribeID);
797
+ resolve(subscribeError);
798
+ }
799
+ });
800
+ });
801
+ }
802
+ removeWindowFromCache(stackName, windowName) {
803
+ let stack = this.storeCache[stackName];
804
+ if (stack) {
805
+ for (let i = 0; i < stack.childWindowIdentifiers.length; i++) {
806
+ const item = stack.childWindowIdentifiers[i];
807
+ if (item.windowName === windowName) {
808
+ stack.childWindowIdentifiers.splice(i, 1);
809
+ return { wasAlwaysOnTop: item.alwaysOnTop, stack };
810
+ }
811
+ }
812
+ }
813
+ return { wasAlwaysOnTop: false, stack };
814
+ }
815
+ async closeStack(stackedWindowIdentifier) {
816
+ let stack = this.storeCache[stackedWindowIdentifier.windowName];
817
+ const lastChild = stack.childWindowIdentifiers[0];
818
+ const { err: getGroupsForWindowError, response } = await RouterClient.query("DockingService.getGroupsForWindow", {
819
+ name: stack.name,
820
+ });
821
+ await this.registerWithDockingManager({ windowIdentifier: lastChild });
822
+ const groups = response.data;
823
+ if (groups) {
824
+ for (const group of groups) {
825
+ RouterClient.transmit("DockingService.joinGroup", {
826
+ groupName: group,
827
+ name: lastChild.windowName,
828
+ });
829
+ }
830
+ }
831
+ const innerChildWrapper = this.childWindow[lastChild.windowName];
832
+ innerChildWrapper._show({ invokedByParent: true });
833
+ const { wrap } = await BaseWindow.getInstance(stackedWindowIdentifier);
834
+ // for now must call close on public wrapper to have wrapper cleanup happen correctly
835
+ Logger.system.debug("StackedWindowManager.removeWindowparent invoking public close", stackedWindowIdentifier, getGroupsForWindowError);
836
+ const { err } = await wrap.close({
837
+ closeChildren: false,
838
+ stackedWindowIdentifier,
839
+ removeFromWorkspace: true,
840
+ invokedByParent: true,
841
+ force: false,
842
+ });
843
+ return err;
844
+ }
845
+ /**
846
+ * Removes a child window from a stacked window. If removed window was visible, then the bottom child window (position 0) in stack will be made visible.
847
+ *
848
+ * @param {object} params Parameters
849
+ * @param {object} params.stackedWindowIdentifier stacked window to operate on
850
+ * @param {object} params.windowIdentifier window to remove
851
+ * @param {boolean=} params.noDocking if true then do not register removed window with docking (the workspace is unaffected)
852
+ * @param {boolean=} params.noVisible if true then do not make window visible when removing it
853
+ * @param {boolean=} params.waitChildClose if true then wait for child wrapper to close before returned (needed for cleanly switching workspaces)
854
+ * @param {boolean=false} params.closeWindow
855
+ * @param {boolean=false} params.noCloseStack if true don't close the stack window when only one child
856
+ * @param {function=} callback function(err)
857
+ * @memberof StackedWindowManager
858
+ * @returns promise
859
+ * @private
860
+ */
861
+ async removeWindow(params, callback = Function.prototype) {
862
+ var _a;
863
+ const { noVisible, noCloseStack, stackedWindowIdentifier, windowIdentifier, noDocking } = params;
864
+ const { wasAlwaysOnTop, stack: thisStackRecord } = this.removeWindowFromCache(stackedWindowIdentifier.windowName, windowIdentifier.windowName);
865
+ Logger.system.debug("StackedWindowManager.removeWindow", params, thisStackRecord);
866
+ if (!thisStackRecord) {
867
+ const error = "StackedWindowManager.removeWindow unknown stackedWindowIdentifier";
868
+ Logger.system.warn(error, params);
869
+ callback(error);
870
+ return { err: error };
871
+ }
872
+ const childWrapper = this.childWindow[windowIdentifier.windowName];
873
+ childWrapper._alwaysOnTop({ alwaysOnTop: wasAlwaysOnTop });
874
+ childWrapper.clearParent(); // remove parent setting from child being remove
875
+ delete this.childNameToSID[windowIdentifier.windowName]; // remove child's mapping to parent stackedWindowIdentifier
876
+ if (((_a = thisStackRecord.visibleWindowIdentifier) === null || _a === void 0 ? void 0 : _a.windowName) === windowIdentifier.windowName) {
877
+ this.removeChildEventListener(thisStackRecord.identifier.windowName, windowIdentifier.windowName, childWrapper);
878
+ thisStackRecord.visibleWindowIdentifier = null;
879
+ }
880
+ // unless specified otherwise, register the remove window with docking
881
+ if (!noDocking) {
882
+ Logger.system.debug("StackedWindowManager.removeWindow registering with docking", stackedWindowIdentifier, windowIdentifier);
883
+ this.registerWithDockingManager({ windowIdentifier });
884
+ }
885
+ // go ahead and set visibility even if closing in order to finish this set of stackedWindow updates
886
+ if (thisStackRecord.childWindowIdentifiers.length && !thisStackRecord.visibleWindowIdentifier) {
887
+ this.setVisibleWindow({
888
+ stackedWindowIdentifier,
889
+ windowIdentifier: thisStackRecord.childWindowIdentifiers[0], // make the first window visible by default
890
+ });
891
+ }
892
+ // unless specified otherwise, show the window being removed from the stacked window (it might not be visible)
893
+ if (!noVisible) {
894
+ childWrapper._show({ invokedByParent: true });
895
+ }
896
+ await this.saveWindowOptions({ closing: false }, params.stackedWindowIdentifier);
897
+ // Notify interested listeners (e.g. BaseWindow wrappers of the removed window) that window was removed from the stack
898
+ Logger.system.debug("StackedWindowManager.removeWindow parent notification", windowIdentifier.windowName);
899
+ RouterClient.publish(`Finsemble.parentChange.${windowIdentifier.windowName}`, {
900
+ type: "Removed",
901
+ stackedWindowIdentifier,
902
+ });
903
+ RouterClient.publish(`Finsemble.parentChange.${windowIdentifier.windowName}`, {});
904
+ childWrapper._restore();
905
+ // if only one child window then the stack is empty and can be unregistered.
906
+ // Pull child out, and close stackedWindow;
907
+ // compare for <= 1 since might be concurrently removing multiple windows from stack for crashed components (i.e. this function is not fully reentrant yet)
908
+ if (!noCloseStack && thisStackRecord.childWindowIdentifiers.length <= 1) {
909
+ Logger.system.debug("StackedWindowManager.removeWindowparent closing stacked window", stackedWindowIdentifier);
910
+ const closeError = await this.closeStack(stackedWindowIdentifier);
911
+ // @early-exit. If you uncomment this return statement, the callback will be invoked twice. That causes errors and looks bad
912
+ // save the child value first because sometimes it's removed from the stackRecord before the query returns, but it still needs to be unregistered
913
+ callback(closeError);
914
+ return { err: closeError };
915
+ }
916
+ Logger.system.debug("StackedWindowManager.removeWindowparent NOT closing stacked window", noCloseStack, thisStackRecord);
917
+ let err = null;
918
+ if (params.waitChildClose) {
919
+ const error = await this.waitForWindowClosed(params.windowIdentifier.windowName);
920
+ if (error)
921
+ err = error.toString();
922
+ }
923
+ callback(err);
924
+ return { err };
925
+ }
926
+ /**
927
+ * Removes a window from the stack then closes it. If removed window was visible, then the bottom child window (position 0) in stack will be made visible.
928
+ *
929
+ * @param {object} params Parameters
930
+ .* @param {object} params.stackedWindowIdentifier stacked window to operate on
931
+ * @param {object} params.windowIdentifier window to delete
932
+ * @param {function=} callback function(err)
933
+ * @memberof StackedWindowManager
934
+ * @private
935
+ */
936
+ deleteWindow(params, callback = Function.prototype) {
937
+ const promiseResolver = async (resolve) => {
938
+ Logger.system.debug("StackedWindowManager.deleteWindow", params);
939
+ if (params.removeFromWorkspace === false) {
940
+ callback();
941
+ resolve();
942
+ }
943
+ else {
944
+ params.noDocking = true;
945
+ await this.removeWindow(params);
946
+ const { wrap } = await BaseWindow.getInstance(params.windowIdentifier);
947
+ wrap.close({
948
+ /*
949
+ * If the close event is sent from the system (i.e. user is closing a stacked window from the taskbar), tell the wrapper to not show the error
950
+ * when attempting to close that window (because the window is already closed from the system).
951
+ * For now we're still calling this function even if it's a system close because we need some way to close a slacked window from the
952
+ * taskbar. We can also change the event name we pass into "this.setupSystemListener" in case of a system close in the WebWindowWrapper file from
953
+ * 'closed' to 'system-closed' so we don't have to close twice. But we decided it's a big change and we should go with a less risky approach in this bug fixing PR.
954
+ */
955
+ suppressError: params.fromSystem,
956
+ invokedByParent: true,
957
+ force: false,
958
+ removeFromWorkspace: true,
959
+ }, (err) => {
960
+ callback(err);
961
+ resolve({ err });
962
+ });
963
+ }
964
+ };
965
+ return new Promise(promiseResolver);
966
+ }
967
+ getPreviouslyVisibleWindow(visibleWindowName, stackedWindowName) {
968
+ if (!visibleWindowName)
969
+ return null;
970
+ const previouslyVisibleWindow = this.childWindow[visibleWindowName]; // will use below to hide previous after setting next
971
+ if (previouslyVisibleWindow) {
972
+ this.removeChildEventListener(stackedWindowName, visibleWindowName, previouslyVisibleWindow);
973
+ }
974
+ return previouslyVisibleWindow;
975
+ }
976
+ /**
977
+ * Sets the visible window within the stack. The previously visible window in stack will be automatically hidden.
978
+ *
979
+ * @param {object} params Parameters
980
+ * @param {object} params.stackedWindowIdentifier stacked window to operate on
981
+ * @param {object} params.windowIdentifier
982
+ * @param {object} params.force if force is true then reset visible even if it is already marked as visible in store (this is for startup)
983
+ * @param {function=} callback function(err)
984
+ * @memberof StackedWindowManager
985
+ * @private
986
+ */
987
+ async setVisibleWindow(params, cb) {
988
+ var _a;
989
+ Logger.system.debug("StackedWindowManager.setVisibleWindow", params);
990
+ const { stackedWindowIdentifier, windowIdentifier } = params;
991
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
992
+ let err = null;
993
+ if (!thisStackRecord) {
994
+ err = "StackedWindowManager.setVisibleWindow unknown stackedWindowIdentifier";
995
+ Logger.system.warn(err, params);
996
+ cb === null || cb === void 0 ? void 0 : cb(err);
997
+ return;
998
+ }
999
+ let previouslyVisibleWindow = this.getPreviouslyVisibleWindow((_a = thisStackRecord.visibleWindowIdentifier) === null || _a === void 0 ? void 0 : _a.windowName, stackedWindowIdentifier.windowName);
1000
+ thisStackRecord.visibleWindowIdentifier = windowIdentifier;
1001
+ const savedBounds = thisStackRecord.bounds;
1002
+ if (!previouslyVisibleWindow || (previouslyVisibleWindow === null || previouslyVisibleWindow === void 0 ? void 0 : previouslyVisibleWindow.windowState) !== constants.WINDOWSTATE.MAXIMIZED) {
1003
+ // set bounds on new visible window
1004
+ this.childWindow[windowIdentifier.windowName]._setBounds({
1005
+ bounds: thisStackRecord.bounds,
1006
+ invokedByParent: true,
1007
+ });
1008
+ }
1009
+ const childWrapper = this.childWindow[windowIdentifier.windowName];
1010
+ childWrapper.disableFrame();
1011
+ this.addChildEventListener(stackedWindowIdentifier.windowName, thisStackRecord.visibleWindowIdentifier.windowName, childWrapper);
1012
+ Logger.system.debug("StackedWindowManager.setVisibleWindow showing", windowIdentifier);
1013
+ const notMinMax = childWrapper.windowOptions.windowState !== constants.WINDOWSTATE.MINIMIZED_WAS_NORMAL && !params.isAddingChildren;
1014
+ /* Workaround for an electron bug where calling show on a aero-snapped window restores the window to it's position prior to being aero-snapped.
1015
+ We can't prevent the window from moving, so after we show the child window we set it's bounds back to it's former position.
1016
+ aeroMode is used to track selecting a window from the preview after snapping. It needs to be set to false in this case as the aero-snap action has already completed.
1017
+
1018
+ This workaround, has the side effect of removing aero-snapped state from the window. However, since only the visible window when the stack was snapped was considered aero-snapped by the OS,
1019
+ the stack already did not respond to subsequent aero-snap commands if another tab was in focus.
1020
+ */
1021
+ if (notMinMax)
1022
+ window.aeroMode = false;
1023
+ await childWrapper._show({
1024
+ invokedByParent: true,
1025
+ });
1026
+ // currently we'll handle a persisted MINIMIZED_WAS_NORMAL state in the stacked window, but not the MINIMIZED_WAS_MAXIMIZED (refactoring window management will address this)
1027
+ if (notMinMax) {
1028
+ if (childWrapper.windowState !== constants.WINDOWSTATE.MAXIMIZED) {
1029
+ childWrapper._setBounds({
1030
+ bounds: savedBounds,
1031
+ invokedByParent: true,
1032
+ });
1033
+ }
1034
+ childWrapper._focus({ invokedByParent: true });
1035
+ Logger.system.debug("StackedWindowManager.setVisibleWindow shown", windowIdentifier);
1036
+ // Doing it this way so that the window in the back is visible when the one in the front hides. This reduces the flickering effect of switching tabs.
1037
+ if ((previouslyVisibleWindow === null || previouslyVisibleWindow === void 0 ? void 0 : previouslyVisibleWindow.windowName) !== childWrapper.windowName) {
1038
+ Logger.system.debug("StackedWindowManager.setVisibleWindow hiding previous", previouslyVisibleWindow);
1039
+ previouslyVisibleWindow === null || previouslyVisibleWindow === void 0 ? void 0 : previouslyVisibleWindow._hide({ invokedByParent: true }, () => {
1040
+ // sometimes (once every 5 tab switches or so) the window gets into a bad state where it is hidden as far as the system is concerned
1041
+ // but it is actually visible but cannot be interacted with. so call hide a second time to fix and really really hide.
1042
+ previouslyVisibleWindow === null || previouslyVisibleWindow === void 0 ? void 0 : previouslyVisibleWindow._hide({ invokedByParent: true });
1043
+ });
1044
+ }
1045
+ }
1046
+ // make sure the window is in front (use case: adding tab to window that isn't in front)
1047
+ childWrapper._bringToFront({ invokedByParent: true });
1048
+ if (!params.noSave) {
1049
+ this.saveWindowOptions({ closing: false }, params.stackedWindowIdentifier);
1050
+ }
1051
+ cb === null || cb === void 0 ? void 0 : cb(err);
1052
+ }
1053
+ // temporary code to workaround tabbing/tiling problem that reshows window when tabs are reordered
1054
+ hideInactiveChildren(thisStackRecord) {
1055
+ Logger.system.debug("StackedWindowManager.hideInactiveChildren");
1056
+ thisStackRecord.childWindowIdentifiers.forEach((identifier) => {
1057
+ // only rehide if not the the visible window
1058
+ if (thisStackRecord.visibleWindowIdentifier &&
1059
+ identifier.windowName !== thisStackRecord.visibleWindowIdentifier.windowName) {
1060
+ const wrap = this.childWindow[identifier.windowName];
1061
+ wrap._hide({ invokedByParent: true });
1062
+ }
1063
+ });
1064
+ }
1065
+ /**
1066
+ * Reorders the stack, but odes not affect visibility
1067
+ *
1068
+ * @param {object} params Parameters
1069
+ * @param {object} params.stackedWindowIdentifier stacked window to operate on
1070
+ * @param {array} params.windowIdentifiers array of windowIdentifiers which provides the new order
1071
+ * @param {function=} callback function(err)
1072
+ * @memberof StackedWindowManager
1073
+ * @private
1074
+ */
1075
+ reorder(params, callback = Function.prototype) {
1076
+ Logger.system.debug("StackedWindowManager.reorder", params);
1077
+ const { stackedWindowIdentifier, windowIdentifiers } = params;
1078
+ // TBD: verify list of identifiers are the same and if not generate error
1079
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
1080
+ let err = null;
1081
+ if (thisStackRecord) {
1082
+ thisStackRecord.childWindowIdentifiers = windowIdentifiers;
1083
+ this.hideInactiveChildren(thisStackRecord); // this is to sidestep a bug in docking/tiling that reshows a moved tab
1084
+ this.saveWindowOptions({ closing: false }, stackedWindowIdentifier);
1085
+ }
1086
+ else {
1087
+ err = "StackedWindowManager.reorder unknown stackedWindowIdentifier";
1088
+ Logger.system.warn(err, params);
1089
+ }
1090
+ if (callback)
1091
+ callback(err);
1092
+ }
1093
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1094
+ // The next section of functions support stacked-window primitives throughout the system.
1095
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1096
+ // stacked window minimize (invoked remotely through stacked window wrapper)
1097
+ minimize(params, callback = Function.prototype) {
1098
+ Logger.system.debug("StackedWindowManager.minimize", params);
1099
+ // if operating on StackedWindow then operation should apply to the visible window
1100
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1101
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1102
+ if (thisStackRecord) {
1103
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1104
+ }
1105
+ else {
1106
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1107
+ return callback("undefined window");
1108
+ }
1109
+ }
1110
+ if (this.isShowing(params)) {
1111
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1112
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1113
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._minimize(params); // invoke function on active window's wrapper
1114
+ }
1115
+ else {
1116
+ Logger.system.error(`StackedWindowManager Warning: minimize received for hidden window ${params.windowIdentifier.windowName}`);
1117
+ }
1118
+ callback(null);
1119
+ }
1120
+ // stacked window maximize (invoked remotely through stacked window wrapper)
1121
+ maximize(params, callback = Function.prototype) {
1122
+ Logger.system.debug("StackedWindowManager.maximize", params);
1123
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1124
+ const visibleWindowWrap = this.childWindow[thisStackRecord.visibleWindowIdentifier.windowName];
1125
+ if (visibleWindowWrap)
1126
+ visibleWindowWrap._maximize();
1127
+ callback();
1128
+ }
1129
+ // stacked window restore (invoked remotely through stacked window wrapper)
1130
+ restore(params, callback = Function.prototype) {
1131
+ Logger.system.debug("StackedWindowManager.restore", params);
1132
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1133
+ const visibleWindowWrap = this.childWindow[thisStackRecord.visibleWindowIdentifier.windowName];
1134
+ if (visibleWindowWrap.windowState === undefined)
1135
+ visibleWindowWrap.windowState = params.windowState;
1136
+ if (visibleWindowWrap)
1137
+ visibleWindowWrap._restore();
1138
+ return callback();
1139
+ }
1140
+ // stacked window focus (invoked remotely through stacked window wrapper)
1141
+ focus(params, callback = Function.prototype) {
1142
+ Logger.system.debug("StackedWindowManager.focus", params);
1143
+ // if operating on StackedWindow then operation should apply to the visible window
1144
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1145
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1146
+ if (thisStackRecord) {
1147
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1148
+ }
1149
+ else {
1150
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1151
+ return callback("undefined window");
1152
+ }
1153
+ }
1154
+ if (this.isShowing(params)) {
1155
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1156
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1157
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._focus(params); // invoke function on active window's wrapper
1158
+ }
1159
+ else {
1160
+ Logger.system.error(`StackedWindowManager Warning: focus received for hidden window ${params.windowIdentifier.windowName}`);
1161
+ }
1162
+ callback(null);
1163
+ }
1164
+ // stacked window bringToFront (invoked remotely through stacked window wrapper)
1165
+ bringToFront(params, callback = Function.prototype) {
1166
+ var _a;
1167
+ params = params || {};
1168
+ Logger.system.debug("StackedWindowManager.bringToFront", params);
1169
+ // if operating on StackedWindow then operation should apply to the visible window
1170
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1171
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1172
+ if (thisStackRecord) {
1173
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1174
+ }
1175
+ else {
1176
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1177
+ return callback("undefined window");
1178
+ }
1179
+ }
1180
+ if (this.isShowing(params)) {
1181
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1182
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1183
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._bringToFront(params); // invoke function on active window's wrapper
1184
+ }
1185
+ else {
1186
+ Logger.system.error(`StackedWindowManager Warning: bringToFront received for hidden window ${(_a = params.stackedWindowIdentifier) === null || _a === void 0 ? void 0 : _a.windowName}`);
1187
+ }
1188
+ callback(null);
1189
+ }
1190
+ saveWindowStateToStore(params, callback = Function.prototype) {
1191
+ this.saveWindowOptions({ closing: false }, params.stackedWindowIdentifier, callback);
1192
+ }
1193
+ mergeBounds(stackRecord, bounds) {
1194
+ bounds.right = bounds.left + bounds.width;
1195
+ const newBounds = {
1196
+ left: bounds.left,
1197
+ right: bounds.right,
1198
+ width: bounds.width,
1199
+ top: bounds.top,
1200
+ bottom: bounds.top + bounds.height,
1201
+ height: bounds.height,
1202
+ };
1203
+ const defaultBounds = {
1204
+ defaultLeft: bounds.left,
1205
+ defaultWidth: bounds.width,
1206
+ defaultTop: bounds.top,
1207
+ defaultHeight: bounds.height,
1208
+ };
1209
+ Object.assign(stackRecord, newBounds);
1210
+ Object.assign(stackRecord, defaultBounds);
1211
+ stackRecord.bounds = newBounds;
1212
+ }
1213
+ // stacked window setBounds (invoked remotely through stacked window wrapper)
1214
+ setBounds(params, callback = Function.prototype) {
1215
+ Logger.system.debug("StackedWindowManager.setBounds", params);
1216
+ let err = null;
1217
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1218
+ if (!thisStackRecord) {
1219
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1220
+ err = "undefined window";
1221
+ }
1222
+ else {
1223
+ // if operating on StackedWindow then operation should apply to the visible window
1224
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1225
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1226
+ }
1227
+ if (this.isShowing(params)) {
1228
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1229
+ this.mergeBounds(thisStackRecord, params.bounds);
1230
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1231
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._setBounds(params); // invoke function on active window's wrapper
1232
+ }
1233
+ else if (params.windowIdentifier) {
1234
+ Logger.system.warn(`StackedWindowManager Warning: setBounds received for hidden window ${params.windowIdentifier}`);
1235
+ }
1236
+ }
1237
+ callback(err);
1238
+ }
1239
+ // stacked window getBoundsFromSystem (invoked remotely through stacked window wrapper)
1240
+ getBoundsFromSystem(params, callback = Function.prototype) {
1241
+ Logger.system.debug("StackedWindowManager.getBoundsFromSystem", params);
1242
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1243
+ // if operating on StackedWindow then operation should apply to the visible window
1244
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1245
+ if (thisStackRecord) {
1246
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1247
+ }
1248
+ else {
1249
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1250
+ return callback("undefined window");
1251
+ }
1252
+ }
1253
+ if (this.isShowing(params)) {
1254
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1255
+ if (!visibleWindow) {
1256
+ const err = `stackedWindowManager: cannot find child window ${params.windowIdentifier.windowName}`;
1257
+ Logger.system.error(err);
1258
+ callback(err);
1259
+ return;
1260
+ }
1261
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1262
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._getBoundsFromSystem(params, (err, bounds) => {
1263
+ // invoke function on active window's wrapper
1264
+ const _bounds = err ? thisStackRecord.bounds : bounds;
1265
+ callback(err, _bounds);
1266
+ });
1267
+ }
1268
+ else if (!this.operatingDirectlyOnStackedWindow(params)) {
1269
+ Logger.system.error(`StackedWindowManager Warning: getBoundsFromSystem received for hidden window ${params.windowIdentifier.windowName}`);
1270
+ callback("getBounds on hidden window");
1271
+ }
1272
+ }
1273
+ // stacked window getBounds (invoked remotely through stacked window wrapper)
1274
+ getBounds(params, callback = Function.prototype) {
1275
+ params = params || {};
1276
+ Logger.system.debug("StackedWindowManager.getBounds", params);
1277
+ let thisStackRecord = null;
1278
+ // if operating on StackedWindow then operation should apply to the visible window
1279
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1280
+ thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1281
+ if (thisStackRecord) {
1282
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1283
+ Logger.system.debug("StackedWindowManager.getBounds", params, thisStackRecord);
1284
+ }
1285
+ else {
1286
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1287
+ callback("undefined window");
1288
+ return;
1289
+ }
1290
+ }
1291
+ if (thisStackRecord && thisStackRecord.bounds) {
1292
+ callback(null, thisStackRecord.bounds);
1293
+ }
1294
+ else if (!thisStackRecord.visibleWindowIdentifier) {
1295
+ // since no visible window use empty bounds; this is to handle an intermittent error that sometimes occurred when creating a stack
1296
+ const emptyBounds = {
1297
+ left: 0,
1298
+ right: 0,
1299
+ width: 10,
1300
+ top: 0,
1301
+ bottom: 0,
1302
+ height: 10,
1303
+ };
1304
+ callback(null, emptyBounds);
1305
+ }
1306
+ else if (this.isShowing(params)) {
1307
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1308
+ if (!visibleWindow) {
1309
+ const err = `stackedWindowManager: cannot find child window ${params.windowIdentifier.windowName}`;
1310
+ Logger.system.error(err);
1311
+ callback(err);
1312
+ return;
1313
+ }
1314
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1315
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._getBounds(params, (err, bounds) => {
1316
+ // invoke function on active window's wrapper
1317
+ const _bounds = err ? this.storeCache[params.stackedWindowIdentifier.windowName].bounds : bounds;
1318
+ callback(err, _bounds);
1319
+ });
1320
+ }
1321
+ else if (!this.operatingDirectlyOnStackedWindow(params)) {
1322
+ Logger.system.error(`StackedWindowManager Warning: getBounds received for hidden window ${params.windowIdentifier.windowName}`);
1323
+ callback("getBounds on hidden window");
1324
+ }
1325
+ callback("something went wrong");
1326
+ }
1327
+ // stacked window updateOptions (invoked remotely through stacked window wrapper)
1328
+ updateOptions(params, callback = Function.prototype) {
1329
+ Logger.system.debug("StackedWindowManager.updateOptions", params);
1330
+ let err = null;
1331
+ // TABBING TBD: put in a getter function for the stacked records to provide common error checking. Docking might invoke for non-existent stacked window
1332
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1333
+ if (thisStackRecord) {
1334
+ // if operating on StackedWindow then operation should apply to the visible window
1335
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1336
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1337
+ }
1338
+ if (this.isShowing(params)) {
1339
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1340
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1341
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._updateOptions(params); // invoke function on active window's wrapper
1342
+ // if (visibleWindow) { // update options is invoked during docking registration while stacked window is being created, so may not have visible window
1343
+ // visibleWindow._updateOptions(params); // invoke function on active window's wrapper
1344
+ // }
1345
+ }
1346
+ else {
1347
+ Logger.system.error(`StackedWindowManager.updateOptions Warning: updateOptions received for hidden window ${params.windowIdentifier.windowName}`);
1348
+ }
1349
+ }
1350
+ else {
1351
+ // else must be an outdated request from a closed stacked window
1352
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1353
+ err = "undefined window";
1354
+ }
1355
+ callback(err);
1356
+ }
1357
+ // stacked window hide (invoked remotely through stacked window wrapper)
1358
+ hide(params, callback = Function.prototype) {
1359
+ Logger.system.debug("StackedWindowManager.hide", params);
1360
+ // if operating on StackedWindow then operation should apply to the visible window
1361
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1362
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1363
+ if (thisStackRecord) {
1364
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1365
+ thisStackRecord.isVisible = false;
1366
+ }
1367
+ else {
1368
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1369
+ return callback("undefined window");
1370
+ }
1371
+ }
1372
+ if (this.isShowing(params)) {
1373
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1374
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1375
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._hide(params); // invoke function on active window's wrapper
1376
+ }
1377
+ else {
1378
+ Logger.system.error(`StackedWindowManager Warning: hide received for hidden window ${params.windowIdentifier.windowName}`);
1379
+ }
1380
+ callback(null);
1381
+ }
1382
+ // stacked window show (invoked remotely through stacked window wrapper)
1383
+ show(params, callback = Function.prototype) {
1384
+ Logger.system.debug("StackedWindowManager.show", params);
1385
+ // if operating on StackedWindow then operation should apply to the visible window
1386
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1387
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1388
+ if (thisStackRecord) {
1389
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1390
+ thisStackRecord.isVisible = true;
1391
+ }
1392
+ else {
1393
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1394
+ return callback("undefined window");
1395
+ }
1396
+ }
1397
+ if (this.isShowing(params)) {
1398
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1399
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1400
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._show(params); // invoke function on active window's wrapper
1401
+ }
1402
+ else {
1403
+ Logger.system.error(`StackedWindowManager Warning: show received for hidden window ${params.windowIdentifier.windowName}`);
1404
+ }
1405
+ callback(null);
1406
+ }
1407
+ // this stacked window close applies to an individual child window (see closeStackedWindow for closing the complete stackedWindow)
1408
+ close(params, callback = Function.prototype) {
1409
+ Logger.system.debug("StackedWindowManager.close", params);
1410
+ // if operating on StackedWindow then operation should apply to the visible window
1411
+ if (params.removeFromWorkspace || this.operatingDirectlyOnStackedWindow(params)) {
1412
+ this.closeStackedWindow(params, callback);
1413
+ }
1414
+ else {
1415
+ this.deleteWindow(params, callback);
1416
+ }
1417
+ }
1418
+ /**
1419
+ * whether the stack itself is visible or not
1420
+ * @param params
1421
+ * @param callback
1422
+ */
1423
+ isStackShowing(params, callback = Function.prototype) {
1424
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1425
+ if (thisStackRecord.isVisible === false) {
1426
+ callback(null, false);
1427
+ return;
1428
+ }
1429
+ callback(null, true);
1430
+ }
1431
+ /**
1432
+ * set Stack to be always on top. Makes all children of the stack always on top and triggers the alwaysOnTop event for the stack
1433
+ */
1434
+ setAlwaysOnTop(params, callback = Function.prototype) {
1435
+ const setAlwaysOnTopPromiseResolver = (resolve) => {
1436
+ Logger.system.debug("StackedWindowManager.setAlwaysOnTop", params);
1437
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1438
+ // if operating on StackedWindow then operation should apply to the visible window
1439
+ if (this.operatingDirectlyOnStackedWindow(params) && !thisStackRecord) {
1440
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1441
+ resolve();
1442
+ return callback("undefined window");
1443
+ }
1444
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1445
+ for (const childWindowIdentifier of thisStackRecord.childWindowIdentifiers) {
1446
+ const childWindow = this.childWindow[childWindowIdentifier.windowName];
1447
+ childWindow._alwaysOnTop(params);
1448
+ }
1449
+ FinsembleWindowInternal.getInstance({ name: thisStackRecord.name }, (err, stackedWindow) => {
1450
+ if (stackedWindow.alwaysOnTop !== params.alwaysOnTop) {
1451
+ stackedWindow.alwaysOnTop = params.alwaysOnTop;
1452
+ stackedWindow.eventManager.trigger("alwaysOnTop", {
1453
+ alwaysOnTop: params.alwaysOnTop,
1454
+ });
1455
+ Logger.system.verbose("StackedWindowManager transmitting event", "alwaysOnTop", this.eventChannelName(thisStackRecord.name, "alwaysOnTop"), event);
1456
+ }
1457
+ callback(null);
1458
+ resolve();
1459
+ });
1460
+ };
1461
+ return new Promise(setAlwaysOnTopPromiseResolver);
1462
+ }
1463
+ // stacked window setOpacity (invoked remotely through stacked window wrapper)
1464
+ setOpacity(params, callback = Function.prototype) {
1465
+ let err = null;
1466
+ Logger.system.debug("StackedWindowManager.setOpacity", params);
1467
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1468
+ if (thisStackRecord) {
1469
+ // if operating on StackedWindow then operation should apply to the visible window
1470
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1471
+ if (!thisStackRecord.visibleWindowIdentifier)
1472
+ return; // there's no window to set opacity on.
1473
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1474
+ }
1475
+ if (this.isShowing(params)) {
1476
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1477
+ params.invokedByParent = true; // prevents wrapper function from recalling parent (causing a loop)
1478
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow._setOpacity(params); // invoke function on active window's wrapper
1479
+ }
1480
+ else {
1481
+ Logger.system.error(`StackedWindowManager Warning: setOpacity received for hidden window ${params.windowIdentifier.windowName}`);
1482
+ }
1483
+ }
1484
+ else {
1485
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1486
+ err = "undefined window";
1487
+ }
1488
+ callback(err);
1489
+ }
1490
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1491
+ // General functions support workspace and docking
1492
+ // TABBING TBD: NEED GENERAL PARAMETERIZED VERSIONS OF THE FUNCTIONS BELOW PULLED OUT OF THE WINDOW CLIENT AND PUT IN COMMON TO SHARE
1493
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1494
+ // placeholder for workspace integration
1495
+ async saveWindowOptions(params, stackedWindowIdentifier, maincallback = Function.prototype) {
1496
+ Logger.system.debug("StackedWindowManager.setComponentState", stackedWindowIdentifier);
1497
+ const thisStackRecord = this.storeCache[stackedWindowIdentifier.windowName];
1498
+ if (!thisStackRecord)
1499
+ return maincallback("stack record not found");
1500
+ const { wrap: stackedWindow } = await FinsembleWindowInternal.getInstance({
1501
+ name: stackedWindowIdentifier.windowName,
1502
+ });
1503
+ stackedWindow.saveCompleteWindowState(thisStackRecord, () => {
1504
+ var _a;
1505
+ const saveChildBounds = (childIdentifier, done) => {
1506
+ Logger.system.debug("StackedWindowManager.saveWindowOptions saveCompleteWindowState child", childIdentifier.windowName);
1507
+ const { bounds } = thisStackRecord;
1508
+ bounds.persistBounds = true;
1509
+ const wrap = this.childWindow[childIdentifier.windowName];
1510
+ if (wrap) {
1511
+ wrap._setBounds({ bounds, invokedByParent: true }, done);
1512
+ }
1513
+ else {
1514
+ FinsembleWindowInternal.getInstance({ name: childIdentifier.windowName }, (err, wrappedWindow) => {
1515
+ wrappedWindow._setBounds({ bounds, invokedByParent: true }, done);
1516
+ });
1517
+ }
1518
+ };
1519
+ Logger.system.debug("StackedWindowManager.saveWindowOptions saveCompleteWindowState start", (_a = stackedWindow.identifier) === null || _a === void 0 ? void 0 : _a.windowName, thisStackRecord);
1520
+ if (!params.closing) {
1521
+ asyncEach(thisStackRecord.childWindowIdentifiers, saveChildBounds, () => {
1522
+ Logger.system.debug("StackedWindowManager.saveWindowOptions saveCompleteWindowState done");
1523
+ RouterClient.publish(`Finsemble.StackedWindow.${stackedWindowIdentifier.windowName}`, thisStackRecord);
1524
+ maincallback();
1525
+ });
1526
+ }
1527
+ else {
1528
+ Logger.system.debug("StackedWindowManager.saveWindowOptions saveCompleteWindowState skipped");
1529
+ RouterClient.publish(`Finsemble.StackedWindow.${stackedWindowIdentifier.windowName}`, thisStackRecord);
1530
+ maincallback();
1531
+ }
1532
+ });
1533
+ }
1534
+ /**
1535
+ * Register a window with docking. It transmits a message to the LauncherService, which registers it as a dockable window.
1536
+ *
1537
+ * @param {object} params Parameters
1538
+ * @param {string} params.windowIdentifier the window to register (may be stacked window or child window)
1539
+ * @private
1540
+ */
1541
+ registerWithDockingManager(params, cb = Function.prototype) {
1542
+ const promiseResolver = (resolve) => {
1543
+ Logger.system.debug("StackedWindowManager.registerWithDockingManager", params);
1544
+ const { windowName } = params.windowIdentifier;
1545
+ params.windowIdentifier.name = windowName;
1546
+ // In the case when we have an existing window, we should use it's options. Otherwise the default options will be applied.
1547
+ const wrap = this.childWindow[windowName];
1548
+ const queryParams = wrap
1549
+ ? {
1550
+ name: windowName,
1551
+ uuid: params.windowIdentifier.uuid,
1552
+ windowType: params.windowIdentifier.windowType,
1553
+ options: {
1554
+ // dockingOptions
1555
+ options: wrap.dockingOptions,
1556
+ snapping: wrap.snapping,
1557
+ tiling: wrap.tiling,
1558
+ tabbing: wrap.tabbing,
1559
+ allowAutoArrange: wrap.allowAutoArrange,
1560
+ canMinimize: wrap.canMinimize,
1561
+ canMaximize: wrap.canMaximize,
1562
+ },
1563
+ }
1564
+ : Object.assign(params.windowIdentifier, params.windowType);
1565
+ RouterClient.query("DockingService.registerWindow", queryParams, () => {
1566
+ Logger.system.debug("StackedWindowManager Docking Registration complete.", params);
1567
+ resolve();
1568
+ if (cb) {
1569
+ cb();
1570
+ }
1571
+ });
1572
+ };
1573
+ return new Promise(promiseResolver);
1574
+ }
1575
+ /**
1576
+ * Unregister a window with docking.
1577
+ *
1578
+ * @param {object} params Parameters
1579
+ * @param {boolean} params.removeFromWorkspace true to remove from workspace
1580
+ * @param {string} params.windowIdentifier window to unregister
1581
+ * @private
1582
+ */
1583
+ deregisterWithDockingManager(params) {
1584
+ Logger.system.debug("StackedWindowManager.deregisterWithDockingManager", params);
1585
+ RouterClient.transmit("DockingService.deregisterWindow", {
1586
+ name: params.windowIdentifier.windowName,
1587
+ userInitiated: params.removeFromWorkspace,
1588
+ });
1589
+ }
1590
+ startMove(params, callback = Function.prototype) {
1591
+ // stacked window setBounds (invoked remotely through stacked window wrapper)
1592
+ Logger.system.debug("StackedWindowManager.startMove", params);
1593
+ let err = null;
1594
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1595
+ if (!thisStackRecord) {
1596
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1597
+ err = "undefined window";
1598
+ }
1599
+ else {
1600
+ // if operating on StackedWindow then operation should apply to the visible window
1601
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1602
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1603
+ }
1604
+ if (this.isShowing(params)) {
1605
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1606
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow.startMove(); // invoke function on active window's wrapper
1607
+ }
1608
+ else {
1609
+ Logger.system.error(`StackedWindowManager Warning: startMove received for hidden window ${params.windowIdentifier}`);
1610
+ }
1611
+ }
1612
+ callback(err);
1613
+ }
1614
+ stopMove(params, callback = Function.prototype) {
1615
+ // stacked window setBounds (invoked remotely through stacked window wrapper)
1616
+ Logger.system.debug("StackedWindowManager.stopMove", params);
1617
+ let err = null;
1618
+ const thisStackRecord = this.storeCache[params.stackedWindowIdentifier.windowName];
1619
+ if (!thisStackRecord) {
1620
+ Logger.system.warn("ignoring command because StackedWindow undefined (probably okay due to its recent close)", params);
1621
+ err = "undefined window";
1622
+ }
1623
+ else {
1624
+ // if operating on StackedWindow then operation should apply to the visible window
1625
+ if (this.operatingDirectlyOnStackedWindow(params)) {
1626
+ params.windowIdentifier = thisStackRecord.visibleWindowIdentifier;
1627
+ }
1628
+ if (this.isShowing(params)) {
1629
+ const visibleWindow = this.childWindow[params.windowIdentifier.windowName];
1630
+ visibleWindow === null || visibleWindow === void 0 ? void 0 : visibleWindow.stopMove(); // invoke function on active window's wrapper
1631
+ }
1632
+ else {
1633
+ Logger.system.error(`StackedWindowManager Warning: stopMove received for hidden window ${params.windowIdentifier}`);
1634
+ }
1635
+ }
1636
+ callback(err);
1637
+ }
1638
+ }
1639
+ const serviceInstance = new StackedWindowManager({});
1640
+ export default serviceInstance;
1641
+ //# sourceMappingURL=stackedWindowManager.js.map