Merge pull request #173 from informatik-ag-ngl/b/restorable_scene

Added ability to execute code when a scene is restored.
Additionally fixed bug not showing "Add user to contact list?" - Alert partially.
This commit is contained in:
delvh 2020-07-04 16:14:00 +02:00 committed by GitHub
commit 329b9a11a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 7 deletions

View File

@ -0,0 +1,25 @@
package envoy.client.ui;
/**
* This interface defines an action that should be performed when a scene gets
* restored from the scene stack in {@link SceneContext}.
* <p>
* Project: <strong>envoy-client</strong><br>
* File: <strong>Restorable.java</strong><br>
* Created: <strong>03.07.2020</strong><br>
*
* @author Leon Hofmeister
* @since Envoy Client v0.1-beta
*/
@FunctionalInterface
public interface Restorable {
/**
* This method is getting called when a scene gets restored.<br>
* Hence, it can contain anything that should be done when the underlying scene
* gets restored.
*
* @since Envoy Client v0.1-beta
*/
void onRestore();
}

View File

@ -90,8 +90,9 @@ public final class SceneContext {
} }
private final Stage stage; private final Stage stage;
private final FXMLLoader loader = new FXMLLoader(); private final FXMLLoader loader = new FXMLLoader();
private final Stack<Scene> sceneStack = new Stack<>(); private final Stack<Scene> sceneStack = new Stack<>();
private final Stack<Object> controllerStack = new Stack<>();
private static final Settings settings = Settings.getInstance(); private static final Settings settings = Settings.getInstance();
@ -120,6 +121,7 @@ public final class SceneContext {
try { try {
final var rootNode = (Parent) loader.load(getClass().getResourceAsStream(sceneInfo.path)); final var rootNode = (Parent) loader.load(getClass().getResourceAsStream(sceneInfo.path));
final var scene = new Scene(rootNode); final var scene = new Scene(rootNode);
controllerStack.push(loader.getController());
sceneStack.push(scene); sceneStack.push(scene);
stage.setScene(scene); stage.setScene(scene);
@ -139,10 +141,16 @@ public final class SceneContext {
*/ */
public void pop() { public void pop() {
sceneStack.pop(); sceneStack.pop();
controllerStack.pop();
if (!sceneStack.isEmpty()) { if (!sceneStack.isEmpty()) {
stage.setScene(sceneStack.peek()); final var newScene = sceneStack.peek();
stage.setScene(newScene);
applyCSS(); applyCSS();
stage.sizeToScene(); stage.sizeToScene();
// If the controller implements the Restorable interface,
// the actions to perform on restoration will be executed here
final var controller = controllerStack.peek();
if (controller instanceof Restorable) ((Restorable) controller).onRestore();
} }
stage.show(); stage.show();
} }
@ -161,7 +169,7 @@ public final class SceneContext {
* @return the controller used by the current scene * @return the controller used by the current scene
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
*/ */
public <T> T getController() { return loader.getController(); } public <T> T getController() { return (T) controllerStack.peek(); }
/** /**
* @return the stage in which the scenes are displayed * @return the stage in which the scenes are displayed

View File

@ -24,6 +24,7 @@ import envoy.client.event.MessageCreationEvent;
import envoy.client.net.Client; import envoy.client.net.Client;
import envoy.client.net.WriteProxy; import envoy.client.net.WriteProxy;
import envoy.client.ui.IconUtil; import envoy.client.ui.IconUtil;
import envoy.client.ui.Restorable;
import envoy.client.ui.SceneContext; import envoy.client.ui.SceneContext;
import envoy.client.ui.listcell.ContactListCellFactory; import envoy.client.ui.listcell.ContactListCellFactory;
import envoy.client.ui.listcell.MessageControl; import envoy.client.ui.listcell.MessageControl;
@ -43,7 +44,7 @@ import envoy.util.EnvoyLog;
* @author Kai S. K. Engelbart * @author Kai S. K. Engelbart
* @since Envoy Client v0.1-beta * @since Envoy Client v0.1-beta
*/ */
public final class ChatScene { public final class ChatScene implements Restorable {
@FXML @FXML
private Label contactLabel; private Label contactLabel;
@ -173,6 +174,9 @@ public final class ChatScene {
if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info"); if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
} }
@Override
public void onRestore() { updateRemainingCharsLabel(); }
/** /**
* Actions to perform when the list of contacts has been clicked. * Actions to perform when the list of contacts has been clicked.
* *

View File

@ -101,14 +101,17 @@ public class ContactSearchScene {
final var alert = new Alert(AlertType.CONFIRMATION); final var alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Add Contact to Contact List"); alert.setTitle("Add Contact to Contact List");
alert.setHeaderText("Add the user " + contact.getName() + " to your contact list?"); alert.setHeaderText("Add the user " + contact.getName() + " to your contact list?");
alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> { // Normally, this would be total BS (we are already on the FX Thread), however
// it could be proven that the creation of this dialog wrapped in
// Platform.runLater is less error-prone than without it
Platform.runLater(() -> alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> {
final var event = new ContactOperation(contact, ElementOperation.ADD); final var event = new ContactOperation(contact, ElementOperation.ADD);
// Sends the event to the server // Sends the event to the server
eventBus.dispatch(new SendEvent(event)); eventBus.dispatch(new SendEvent(event));
// Updates the UI // Updates the UI
eventBus.dispatch(event); eventBus.dispatch(event);
logger.log(Level.INFO, "Added contact " + contact); logger.log(Level.INFO, "Added contact " + contact);
}); }));
} }
} }