Skip to content

Commit eaf46e5

Browse files
authored
Merge pull request #3507 from ControlSystemStudio/snapshot_controller_refactoring
Fix close checks in save&restore
2 parents 084f918 + 0229530 commit eaf46e5

File tree

17 files changed

+413
-449
lines changed

17 files changed

+413
-449
lines changed
23.7 KB
Loading

app/save-and-restore/app/doc/index.rst

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,25 @@ Prior to restore user has the option to:
324324

325325
Restoring from a composite snapshot works in the same manner as the restore operation from a single-snapshot.
326326

327+
Filter PV items in list
328+
^^^^^^^^^^^^^^^^^^^^^^^
329+
The list of items in the snapshot view can be filtered based on the PV name. See screenshot for highlighted UI element
330+
where user may specify a string pattern to match PV names. Non-matching items will be hidden from the list view and
331+
**also excluded from a restore operation**.
332+
333+
To filter the view without excluding PV items from a restore operation, user needs to tick the “Preserve selection…” checkbox.
334+
335+
.. image:: images/filter-pv-items.png
336+
:width: 80%
337+
338+
327339
Restore from context menu
328340
^^^^^^^^^^^^^^^^^^^^^^^^^
329341

330342
User may invoke a restore operation (from client or from service) from context menu items in the tree
331-
view or in the search-and-filer view. In this case user will not have the possibility to unselect specific PVs.
332-
However, PV items configured as read-only will not be restored.
343+
view or in the search-and-filter view. In this case user will not have the possibility to deselect specific PVs.
344+
Filtering/exclusion based on PV name will not be possible either.
345+
However, PV items configured as read-only will always be excluded from a restore operation.
333346

334347
Restore result
335348
^^^^^^^^^^^^^^

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/Messages.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ public class Messages {
3434
public static String cannotCompareTitle;
3535
public static String closeConfigurationWarning;
3636
public static String closeCompositeSnapshotWarning;
37-
public static String closeTabPrompt;
37+
public static String closeSnapshotWarning;
38+
public static String closeCompositeSnapshotTabPrompt;
39+
public static String closeConfigurationTabPrompt;
40+
public static String closeSnapshotTabPrompt;
3841
public static String compositeSnapshotConsistencyCheckFailed;
3942
public static String contextMenuAddTag;
4043
@Deprecated
@@ -120,7 +123,6 @@ public class Messages {
120123

121124
public static String overwrite;
122125
public static String paste;
123-
public static String promptCloseSnapshotTabContent;
124126
public static String promptDeleteSelectedTitle;
125127
public static String promptDeleteSelectedHeader;
126128
public static String promptDeleteSelectedContent;

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/SaveAndRestoreInstance.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818

1919
package org.phoebus.applications.saveandrestore;
2020

21+
import javafx.application.Platform;
2122
import javafx.fxml.FXMLLoader;
2223
import org.phoebus.applications.saveandrestore.ui.SaveAndRestoreController;
2324
import org.phoebus.framework.nls.NLS;
2425
import org.phoebus.framework.persistence.Memento;
2526
import org.phoebus.framework.spi.AppDescriptor;
2627
import org.phoebus.framework.spi.AppInstance;
2728
import org.phoebus.security.tokens.ScopedAuthenticationToken;
28-
import org.phoebus.ui.docking.DockItem;
29+
import org.phoebus.ui.docking.DockItemWithInput;
2930
import org.phoebus.ui.docking.DockPane;
3031

3132
import java.net.URI;
@@ -37,9 +38,10 @@
3738

3839
public class SaveAndRestoreInstance implements AppInstance {
3940

41+
4042
private final AppDescriptor appDescriptor;
4143
private final SaveAndRestoreController saveAndRestoreController;
42-
private DockItem dockItem;
44+
private DockItemWithInput dockItem;
4345

4446
public static SaveAndRestoreInstance INSTANCE;
4547

@@ -53,21 +55,65 @@ public SaveAndRestoreInstance(AppDescriptor appDescriptor) {
5355
ResourceBundle resourceBundle = NLS.getMessages(Messages.class);
5456
loader.setResources(resourceBundle);
5557
loader.setLocation(SaveAndRestoreApplication.class.getResource("ui/SaveAndRestoreUI.fxml"));
56-
dockItem = new DockItem(this, loader.load());
58+
dockItem = new DockItemWithInput(this, loader.load(), null, null, null);
5759
} catch (Exception e) {
5860
Logger.getLogger(SaveAndRestoreInstance.class.getName()).log(Level.SEVERE, "Failed loading fxml", e);
5961
}
6062

6163
saveAndRestoreController = loader.getController();
64+
65+
// When user closes Phoebus...
6266
dockItem.addCloseCheck(() -> {
63-
saveAndRestoreController.handleTabClosed();
64-
INSTANCE = null;
65-
return CompletableFuture.completedFuture(true);
67+
boolean mayClose = mayClose();
68+
if (mayClose) {
69+
saveAndRestoreController.handleTabClosed();
70+
INSTANCE = null;
71+
}
72+
return CompletableFuture.completedFuture(mayClose);
73+
});
74+
75+
// When user closes save&restore app...
76+
dockItem.setOnCloseRequest(event -> {
77+
if (mayClose()) {
78+
saveAndRestoreController.handleTabClosed();
79+
INSTANCE = null;
80+
} else {
81+
event.consume();
82+
}
6683
});
6784

6885
DockPane.getActiveDockPane().addTab(dockItem);
6986
}
7087

88+
/**
89+
* Checks with each tab if it may be closed.
90+
*
91+
* @return <code>false</code> if any of the tabs contains unsaved data, otherwise <code>true</code>.
92+
*/
93+
private boolean mayClose() {
94+
if (Platform.isFxApplicationThread()) {
95+
return saveAndRestoreController.doCloseCheck();
96+
} else {
97+
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
98+
Platform.runLater(() -> {
99+
try {
100+
boolean okToClose = saveAndRestoreController.doCloseCheck();
101+
completableFuture.complete(okToClose);
102+
} catch (Exception e) {
103+
Logger.getLogger(SaveAndRestoreInstance.class.getName()).log(Level.SEVERE,
104+
"Got exception when checking if OK to close", e);
105+
completableFuture.complete(true);
106+
}
107+
});
108+
try {
109+
return completableFuture.get();
110+
} catch (Exception e) {
111+
Logger.getLogger(SaveAndRestoreInstance.class.getName()).log(Level.WARNING, "Got exception when waiting for close check evaluation", e);
112+
return true;
113+
}
114+
}
115+
}
116+
71117
@Override
72118
public AppDescriptor getAppDescriptor() {
73119
return appDescriptor;

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/SaveAndRestoreBaseController.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,14 @@ public SimpleStringProperty getUserIdentity() {
7676
protected void handleWebSocketMessage(SaveAndRestoreWebSocketMessage<?> webSocketMessage){
7777
}
7878

79+
/**
80+
* Performs suitable cleanup, e.g. close web socket and PVs (where applicable).
81+
*/
82+
public abstract void handleTabClosed();
7983

80-
protected boolean handleTabClosed(){
81-
return true;
82-
}
84+
/**
85+
* Checks if the tab may be closed, e.g. if data managed in the UI has been saved.
86+
* @return <code>false</code> if tab contains unsaved data, otherwise <code>true</code>
87+
*/
88+
public abstract boolean doCloseCheck();
8389
}

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/SaveAndRestoreController.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,11 +937,11 @@ public void saveLocalState() {
937937
}
938938

939939
@Override
940-
public boolean handleTabClosed() {
940+
public void handleTabClosed() {
941+
tabPane.getTabs().forEach(t -> ((SaveAndRestoreTab)t).handleTabClosed());
941942
saveLocalState();
942943
webSocketClientService.closeWebSocket();
943944
filterActivators.forEach(FilterActivator::stop);
944-
return true;
945945
}
946946

947947
/**
@@ -1436,7 +1436,7 @@ private void addOptionalLoggingMenuItem() {
14361436
}
14371437

14381438
@Override
1439-
public void handleWebSocketMessage(SaveAndRestoreWebSocketMessage saveAndRestoreWebSocketMessage) {
1439+
public void handleWebSocketMessage(SaveAndRestoreWebSocketMessage<?> saveAndRestoreWebSocketMessage) {
14401440
switch (saveAndRestoreWebSocketMessage.messageType()) {
14411441
case NODE_ADDED -> nodeAdded((String) saveAndRestoreWebSocketMessage.payload());
14421442
case NODE_REMOVED -> nodeRemoved((String) saveAndRestoreWebSocketMessage.payload());
@@ -1496,4 +1496,14 @@ private void handleWebSocketDisconnected() {
14961496
serviceConnected.setValue(false);
14971497
saveLocalState();
14981498
}
1499+
1500+
@Override
1501+
public boolean doCloseCheck(){
1502+
for(Tab tab : tabPane.getTabs()){
1503+
if(!((SaveAndRestoreTab)tab).doCloseCheck()){
1504+
return false;
1505+
}
1506+
}
1507+
return true;
1508+
}
14991509
}

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/SaveAndRestoreTab.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
public abstract class SaveAndRestoreTab extends Tab implements WebSocketMessageHandler {
3939

4040
protected SaveAndRestoreBaseController controller;
41-
protected WebSocketClientService webSocketClientService;
4241

4342
public SaveAndRestoreTab() {
4443
ContextMenu contextMenu = new ContextMenu();
@@ -63,17 +62,13 @@ public SaveAndRestoreTab() {
6362
contextMenu.getItems().addAll(closeAll, closeOthers);
6463
setContextMenu(contextMenu);
6564

66-
webSocketClientService = WebSocketClientService.getInstance();
67-
6865
setOnCloseRequest(event -> {
69-
if (!controller.handleTabClosed()) {
70-
event.consume();
66+
if (doCloseCheck()) {
67+
handleTabClosed();
7168
} else {
72-
webSocketClientService.removeWebSocketMessageHandler(this);
69+
event.consume();
7370
}
7471
});
75-
76-
webSocketClientService.addWebSocketMessageHandler(this);
7772
}
7873

7974
/**
@@ -89,4 +84,19 @@ public void secureStoreChanged(List<ScopedAuthenticationToken> validTokens) {
8984
public void handleWebSocketMessage(SaveAndRestoreWebSocketMessage<?> saveAndRestoreWebSocketMessage) {
9085

9186
}
87+
88+
/**
89+
* Performs suitable cleanup, e.g. close web socket and PVs (where applicable).
90+
*/
91+
public void handleTabClosed() {
92+
controller.handleTabClosed();
93+
}
94+
95+
/**
96+
* Checks if the tab may be closed, e.g. if data managed in the UI has been saved.
97+
* @return <code>false</code> if tab contains unsaved data, otherwise <code>true</code>
98+
*/
99+
public boolean doCloseCheck() {
100+
return controller.doCloseCheck();
101+
}
92102
}

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/configuration/ConfigurationController.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.phoebus.framework.jobs.JobManager;
6868
import org.phoebus.framework.selection.SelectionService;
6969
import org.phoebus.ui.application.ContextMenuHelper;
70+
import org.phoebus.ui.dialog.DialogHelper;
7071
import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog;
7172
import org.phoebus.ui.javafx.FocusUtil;
7273
import org.phoebus.ui.javafx.ImageCache;
@@ -86,7 +87,7 @@ public class ConfigurationController extends SaveAndRestoreBaseController implem
8687

8788
@FXML
8889
@SuppressWarnings("unused")
89-
private BorderPane root;
90+
private BorderPane borderPane;
9091

9192
@FXML
9293
@SuppressWarnings("unused")
@@ -485,7 +486,7 @@ public void loadConfiguration(final Node node) {
485486
try {
486487
configurationData = saveAndRestoreService.getConfiguration(node.getUniqueId());
487488
} catch (Exception e) {
488-
Platform.runLater(() -> ExceptionDetailsErrorDialog.openError(root, Messages.errorGeneric, Messages.errorUnableToRetrieveData, e));
489+
Platform.runLater(() -> ExceptionDetailsErrorDialog.openError(borderPane, Messages.errorGeneric, Messages.errorUnableToRetrieveData, e));
489490
return;
490491
}
491492

@@ -513,24 +514,28 @@ public void loadConfiguration(final Node node) {
513514
}
514515

515516
/**
516-
* Handles clean-up when the associated {@link ConfigurationTab} is closed.
517517
* A check is made if content is dirty, in which case user is prompted to cancel or close anyway.
518518
*
519519
* @return <code>true</code> if content is not dirty or user chooses to close anyway,
520520
* otherwise <code>false</code>.
521521
*/
522522
@Override
523-
public boolean handleTabClosed() {
523+
public boolean doCloseCheck() {
524524
if (dirty.get()) {
525525
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
526-
alert.setTitle(Messages.closeTabPrompt);
526+
alert.setTitle(Messages.closeConfigurationTabPrompt);
527527
alert.setContentText(Messages.closeConfigurationWarning);
528+
DialogHelper.positionDialog(alert, borderPane, -200, -200);
528529
Optional<ButtonType> result = alert.showAndWait();
529530
return result.isPresent() && result.get().equals(ButtonType.OK);
530-
} else {
531-
webSocketClientService.removeWebSocketMessageHandler(this);
532-
return true;
533531
}
532+
533+
return true;
534+
}
535+
536+
@Override
537+
public void handleTabClosed(){
538+
webSocketClientService.removeWebSocketMessageHandler(this);
534539
}
535540

536541
@Override

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/search/SearchAndFilterTab.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,4 @@ public SearchAndFilterTab(SaveAndRestoreController saveAndRestoreController) {
7575
setText(Messages.search);
7676
setGraphic(new ImageView(ImageCache.getImage(ImageCache.class, "/icons/sar-search_18x18.png")));
7777
}
78-
79-
public void filterActivated(String filterName){
80-
((SearchAndFilterViewController)controller).filterActivated(filterName);
81-
}
82-
83-
public void filterDeactivated(String filterName){
84-
((SearchAndFilterViewController)controller).filterDeactivated(filterName);
85-
}
8678
}

app/save-and-restore/app/src/main/java/org/phoebus/applications/saveandrestore/ui/search/SearchAndFilterViewController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -648,11 +648,13 @@ public void handleWebSocketMessage(SaveAndRestoreWebSocketMessage<?> saveAndRest
648648
}
649649
}
650650

651-
public void filterActivated(String filterName){
652-
651+
@Override
652+
public void handleTabClosed(){
653+
webSocketClientService.removeWebSocketMessageHandler(this);
653654
}
654655

655-
public void filterDeactivated(String filterName){
656-
656+
@Override
657+
public boolean doCloseCheck(){
658+
return true;
657659
}
658660
}

0 commit comments

Comments
 (0)