CSSTUDIO-1761 (Part 1/2) Add functionality to the menu of the main window for adding a layout to the current layout. #2550
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
CSSTUDIO-1761
asks for implementation of:This merge-request implements point 2. Point 1. is implemented in merge-request #2551.
This merge-request adds a sub-menu called "Add Layout" under the menu "Window" of the main window of the Phoebus application. In contrast to the sub-menu "Load Layout", "Add Layout" doesn't replace the current layout with the loaded layout, instead it adds the loaded layout in by opening one or more new windows, leaving the currently opened layout intact.
The functionality implemented in this merge-request is more general than what is described under point 2.: not only individual windows can be added to the current layout, but any layout (with any number of windows) that has been saved.
The main part of the implementation of "Add Layout" is carried out in the function
addLayoutToCurrentLayout()
in the classPhoebusApplication
. The implementation leverages the existing functionality of "restoring" stages from objects of typeMementoTree
by calling the functionMementoHelper.restoreStage()
.MementoHelper.restoreStage()
(re-)creates the individual applications of a stored layout by invoking the corresponding instances ofAppDescriptor.create()
for the applications in question. Many (but not all) applications implement functionality inAppDescriptor.create()
that locates an already existing copy of the application in question, which, if such an instance is found, does not create a new instance of the application, but instead puts the focus on the existing instance and possibly refreshes its content.The functionality that
AppDescriptor.create()
often implements of selecting and possibly refreshing an already existing instance instead of creating a new instance leads to three complications for the implementation of the "Add Layout" sub-menu. If a new instance of an application is not created, but instead an existing instance is given focus, then:AppDescriptor.create()
) will be opened, possibly changing which tab is opened in a window before "Add Layout" was invoked. This should not be the case, since the windows that were already open should be unchanged after invoking "Add Layout";AppDescriptor.create()
. This should not happen, since the windows that were already open should be unchanged after invoking "Add Layout".Points 1. and 2. have been addressed, but I have not found a way to address point 3.
Point 1. is addressed by iterating through the newly created instances of
Stage
, checking whether they contain any tabs. If an instance doesn't contain any tabs, then no application was restored to the instance in question, and the stage in question is closed. The main difficulty in implementing this check is that it can only be performed once every created instance ofPane
has an associated instance ofScene
. To this end, the functionDockStage.deferUntilAllPanesOfStageHaveScenes()
was implemented.DockStage.deferUntilAllPanesOfStageHaveScenes()
is implemented usingDockPane.deferUntilInScene()
, whose implementation was improved (also fixing #2544):ChangeListener
instead of by trying to wait.f1()
is deferred beforef2()
is deferred, thenf1()
will be invoked beforef2()
is invoked. This is necessary in order to guarantee that the check for whether any tabs have been restored is run after the code restoring instances is run.Point 2. is addressed by iterating through the existing panes of the application before creating new stages, saving the selected item in each pane. After the new stages have been restored, the selected items of each original pane are restored. Finally, the newly created stages are given focus.
Point 3. is, as stated above, not addressed, and any suggestions on how to address point 3. are very welcome.