Skip to content

Commit c8201fc

Browse files
committed
Improve close checks in save&restore
1 parent be103c7 commit c8201fc

File tree

14 files changed

+174
-88
lines changed

14 files changed

+174
-88
lines changed

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: 46 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,59 @@ 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+
boolean okToClose = saveAndRestoreController.doCloseCheck();
100+
completableFuture.complete(okToClose);
101+
});
102+
try {
103+
return completableFuture.get();
104+
} catch (Exception e) {
105+
Logger.getLogger(SaveAndRestoreInstance.class.getName()).log(Level.WARNING, "Got exception when waiting for close check evaluation", e);
106+
return true;
107+
}
108+
}
109+
}
110+
71111
@Override
72112
public AppDescriptor getAppDescriptor() {
73113
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
@@ -66,6 +66,7 @@
6666
import org.phoebus.framework.jobs.JobManager;
6767
import org.phoebus.framework.selection.SelectionService;
6868
import org.phoebus.ui.application.ContextMenuHelper;
69+
import org.phoebus.ui.dialog.DialogHelper;
6970
import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog;
7071
import org.phoebus.ui.javafx.FocusUtil;
7172
import org.phoebus.ui.javafx.ImageCache;
@@ -85,7 +86,7 @@ public class ConfigurationController extends SaveAndRestoreBaseController implem
8586

8687
@FXML
8788
@SuppressWarnings("unused")
88-
private BorderPane root;
89+
private BorderPane borderPane;
8990

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

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

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

535540
@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
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,13 @@ public void handleWebSocketMessage(SaveAndRestoreWebSocketMessage<?> saveAndRest
419419
}
420420
}
421421

422-
public boolean handleTabClosed() {
422+
@Override
423+
public void handleTabClosed() {
423424
webSocketClientService.removeWebSocketMessageHandler(this);
425+
}
426+
427+
@Override
428+
public boolean doCloseCheck(){
424429
return true;
425430
}
426431
}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -423,17 +423,21 @@ public void loadCompositeSnapshot(final Node node) {
423423
}
424424

425425
@Override
426-
public boolean handleTabClosed() {
426+
public boolean doCloseCheck() {
427427
if (dirty.get()) {
428428
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
429-
alert.setTitle(Messages.closeTabPrompt);
429+
alert.setTitle(Messages.closeCompositeSnapshotTabPrompt);
430430
alert.setContentText(Messages.closeCompositeSnapshotWarning);
431+
DialogHelper.positionDialog(alert, borderPane, -200, -200);
431432
Optional<ButtonType> result = alert.showAndWait();
432433
return result.isPresent() && result.get().equals(ButtonType.OK);
433-
} else {
434-
webSocketClientService.removeWebSocketMessageHandler(this);
435-
return true;
436434
}
435+
return true;
436+
}
437+
438+
@Override
439+
public void handleTabClosed(){
440+
webSocketClientService.removeWebSocketMessageHandler(this);
437441
}
438442

439443
/**

0 commit comments

Comments
 (0)