Improve Scene Switching #109
@@ -6,7 +6,7 @@ import envoy.data.User.UserStatus;
 | 
			
		||||
 | 
			
		||||
import envoy.client.data.Context;
 | 
			
		||||
import envoy.client.helper.ShutdownHelper;
 | 
			
		||||
import envoy.client.ui.SceneContext.SceneInfo;
 | 
			
		||||
import envoy.client.ui.SceneInfo;
 | 
			
		||||
import envoy.client.util.UserUtil;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import java.util.*;
 | 
			
		||||
 | 
			
		||||
import javafx.scene.input.KeyCombination;
 | 
			
		||||
 | 
			
		||||
import envoy.client.ui.SceneContext.SceneInfo;
 | 
			
		||||
import envoy.client.ui.SceneInfo;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Contains all keyboard shortcuts used throughout the application.
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ import java.io.IOException;
 | 
			
		||||
import java.util.Stack;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
 | 
			
		||||
import javafx.application.Platform;
 | 
			
		||||
import javafx.fxml.FXMLLoader;
 | 
			
		||||
import javafx.scene.*;
 | 
			
		||||
import javafx.stage.Stage;
 | 
			
		||||
@@ -28,51 +27,11 @@ import envoy.client.event.*;
 | 
			
		||||
 */
 | 
			
		||||
public final class SceneContext implements EventListener {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Contains information about different scenes and their FXML resource files.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @author Kai S. K. Engelbart
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public enum SceneInfo {
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * The main scene in which the chat screen is displayed.
 | 
			
		||||
		 *
 | 
			
		||||
		 * @since Envoy Client v0.1-beta
 | 
			
		||||
		 */
 | 
			
		||||
		CHAT_SCENE("/fxml/ChatScene.fxml"),
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * The scene in which the settings screen is displayed.
 | 
			
		||||
		 *
 | 
			
		||||
		 * @since Envoy Client v0.1-beta
 | 
			
		||||
		 */
 | 
			
		||||
		SETTINGS_SCENE("/fxml/SettingsScene.fxml"),
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * The scene in which the login screen is displayed.
 | 
			
		||||
		 *
 | 
			
		||||
		 * @since Envoy Client v0.1-beta
 | 
			
		||||
		 */
 | 
			
		||||
		LOGIN_SCENE("/fxml/LoginScene.fxml");
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * The path to the FXML resource.
 | 
			
		||||
		 */
 | 
			
		||||
		public final String path;
 | 
			
		||||
 | 
			
		||||
		SceneInfo(String path) {
 | 
			
		||||
			this.path = path;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private final Stage			stage;
 | 
			
		||||
	private final FXMLLoader	loader			= new FXMLLoader();
 | 
			
		||||
	private final Stack<Scene>	sceneStack		= new Stack<>();
 | 
			
		||||
	private final Stack<Object>	controllerStack	= new Stack<>();
 | 
			
		||||
	private final Stack<Parent>	roots		= new Stack<>();
 | 
			
		||||
	private final Stack<Object>	controllers	= new Stack<>();
 | 
			
		||||
 | 
			
		||||
	private static final Settings settings = Settings.getInstance();
 | 
			
		||||
	private Scene scene;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Initializes the scene context.
 | 
			
		||||
@@ -88,44 +47,44 @@ public final class SceneContext implements EventListener {
 | 
			
		||||
	/**
 | 
			
		||||
	 * Loads a new scene specified by a scene info.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param sceneInfo specifies the scene to load
 | 
			
		||||
	 * @param info specifies the scene to load
 | 
			
		||||
	 * @throws RuntimeException if the loading process fails
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public void load(SceneInfo sceneInfo) {
 | 
			
		||||
		EnvoyLog.getLogger(SceneContext.class).log(Level.FINER, "Loading scene " + sceneInfo);
 | 
			
		||||
		loader.setRoot(null);
 | 
			
		||||
		loader.setController(null);
 | 
			
		||||
	public void load(SceneInfo info) {
 | 
			
		||||
		EnvoyLog.getLogger(SceneContext.class).log(Level.FINER, "Loading scene " + info);
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			final var	rootNode	=
 | 
			
		||||
				(Parent) loader.load(getClass().getResourceAsStream(sceneInfo.path));
 | 
			
		||||
			final var	scene		= new Scene(rootNode);
 | 
			
		||||
			final var	controller	= loader.getController();
 | 
			
		||||
			controllerStack.push(controller);
 | 
			
		||||
 | 
			
		||||
			sceneStack.push(scene);
 | 
			
		||||
			// Load root node and controller
 | 
			
		||||
			var		loader		= new FXMLLoader();
 | 
			
		||||
			Parent	root		= loader.load(getClass().getResourceAsStream(info.path));
 | 
			
		||||
			Object	controller	= loader.getController();
 | 
			
		||||
			roots.push(root);
 | 
			
		||||
			controllers.push(controller);
 | 
			
		||||
 | 
			
		||||
			if (scene == null) {
 | 
			
		||||
 | 
			
		||||
				// One-time scene initialization
 | 
			
		||||
				scene = new Scene(root, stage.getWidth(), stage.getHeight());
 | 
			
		||||
				applyCSS();
 | 
			
		||||
				stage.setScene(scene);
 | 
			
		||||
			} else {
 | 
			
		||||
				scene.setRoot(root);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Remove previous keyboard shortcuts
 | 
			
		||||
			scene.getAccelerators().clear();
 | 
			
		||||
 | 
			
		||||
			// Supply the global custom keyboard shortcuts for that scene
 | 
			
		||||
			scene.getAccelerators()
 | 
			
		||||
				.putAll(GlobalKeyShortcuts.getInstance().getKeyboardShortcuts(sceneInfo));
 | 
			
		||||
				.putAll(GlobalKeyShortcuts.getInstance().getKeyboardShortcuts(info));
 | 
			
		||||
 | 
			
		||||
			// Supply the scene specific keyboard shortcuts
 | 
			
		||||
			if (controller instanceof KeyboardMapping)
 | 
			
		||||
				scene.getAccelerators()
 | 
			
		||||
					.putAll(((KeyboardMapping) controller).getKeyboardShortcuts());
 | 
			
		||||
 | 
			
		||||
			// The LoginScene is the only scene not intended to be resized
 | 
			
		||||
			// As strange as it seems, this is needed as otherwise the LoginScene won't be
 | 
			
		||||
			// displayed on some OS (...Debian...)
 | 
			
		||||
			stage.sizeToScene();
 | 
			
		||||
			Platform.runLater(() -> stage.setResizable(sceneInfo != SceneInfo.LOGIN_SCENE));
 | 
			
		||||
			applyCSS();
 | 
			
		||||
			stage.show();
 | 
			
		||||
		} catch (final IOException e) {
 | 
			
		||||
			EnvoyLog.getLogger(SceneContext.class).log(Level.SEVERE,
 | 
			
		||||
| 
					
	
	
	
	
	
	
	
	 
					
					kske marked this conversation as resolved
					
				 
				 | 
			||||
				String.format("Could not load scene for %s: ", sceneInfo), e);
 | 
			
		||||
		} catch (IOException e) {
 | 
			
		||||
			throw new RuntimeException(e);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -137,29 +96,30 @@ public final class SceneContext implements EventListener {
 | 
			
		||||
	 */
 | 
			
		||||
	public void pop() {
 | 
			
		||||
 | 
			
		||||
		// Pop scene and controller
 | 
			
		||||
		sceneStack.pop();
 | 
			
		||||
		controllerStack.pop();
 | 
			
		||||
		// Pop current root node and controller
 | 
			
		||||
		roots.pop();
 | 
			
		||||
		controllers.pop();
 | 
			
		||||
 | 
			
		||||
		// Apply new scene if present
 | 
			
		||||
		if (!sceneStack.isEmpty()) {
 | 
			
		||||
			final var newScene = sceneStack.peek();
 | 
			
		||||
			stage.setScene(newScene);
 | 
			
		||||
			applyCSS();
 | 
			
		||||
			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 (!roots.isEmpty()) {
 | 
			
		||||
			scene.setRoot(roots.peek());
 | 
			
		||||
 | 
			
		||||
			// Invoke restore if controller is restorable
 | 
			
		||||
			var controller = controllers.peek();
 | 
			
		||||
			if (controller instanceof Restorable)
 | 
			
		||||
				((Restorable) controller).onRestore();
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			// Remove the current scene entirely
 | 
			
		||||
			scene = null;
 | 
			
		||||
			stage.setScene(null);
 | 
			
		||||
		}
 | 
			
		||||
		stage.show();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void applyCSS() {
 | 
			
		||||
		if (!sceneStack.isEmpty()) {
 | 
			
		||||
			final var	styleSheets	= stage.getScene().getStylesheets();
 | 
			
		||||
			final var	themeCSS	= "/css/" + settings.getCurrentTheme() + ".css";
 | 
			
		||||
		if (scene != null) {
 | 
			
		||||
			var	styleSheets	= scene.getStylesheets();
 | 
			
		||||
			var	themeCSS	= "/css/" + Settings.getInstance().getCurrentTheme() + ".css";
 | 
			
		||||
			styleSheets.clear();
 | 
			
		||||
			styleSheets.addAll(getClass().getResource("/css/base.css").toExternalForm(),
 | 
			
		||||
				getClass().getResource(themeCSS).toExternalForm());
 | 
			
		||||
@@ -168,8 +128,8 @@ public final class SceneContext implements EventListener {
 | 
			
		||||
 | 
			
		||||
	@Event(eventType = Logout.class, priority = 150)
 | 
			
		||||
	private void onLogout() {
 | 
			
		||||
		sceneStack.clear();
 | 
			
		||||
		controllerStack.clear();
 | 
			
		||||
		roots.clear();
 | 
			
		||||
		controllers.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Event(priority = 150, eventType = ThemeChangeEvent.class)
 | 
			
		||||
@@ -182,7 +142,7 @@ public final class SceneContext implements EventListener {
 | 
			
		||||
	 * @return the controller used by the current scene
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public <T> T getController() { return (T) controllerStack.peek(); }
 | 
			
		||||
	public <T> T getController() { return (T) controllers.peek(); }
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @return the stage in which the scenes are displayed
 | 
			
		||||
@@ -194,5 +154,5 @@ public final class SceneContext implements EventListener {
 | 
			
		||||
	 * @return whether the scene stack is empty
 | 
			
		||||
	 * @since Envoy Client v0.2-beta
 | 
			
		||||
	 */
 | 
			
		||||
	public boolean isEmpty() { return sceneStack.isEmpty(); }
 | 
			
		||||
	public boolean isEmpty() { return roots.isEmpty(); }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								client/src/main/java/envoy/client/ui/SceneInfo.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								client/src/main/java/envoy/client/ui/SceneInfo.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
package envoy.client.ui;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Contains information about different scenes and their FXML resource files.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Kai S. K. Engelbart
 | 
			
		||||
 * @since Envoy Client v0.1-beta
 | 
			
		||||
 */
 | 
			
		||||
public enum SceneInfo {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The main scene in which the chat screen is displayed.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	CHAT_SCENE("/fxml/ChatScene.fxml"),
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The scene in which the settings screen is displayed.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	SETTINGS_SCENE("/fxml/SettingsScene.fxml"),
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The scene in which the login screen is displayed.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @since Envoy Client v0.1-beta
 | 
			
		||||
	 */
 | 
			
		||||
	LOGIN_SCENE("/fxml/LoginScene.fxml");
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The path to the FXML resource.
 | 
			
		||||
	 */
 | 
			
		||||
	public final String path;
 | 
			
		||||
 | 
			
		||||
	SceneInfo(String path) {
 | 
			
		||||
		this.path = path;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,6 @@ import envoy.client.data.*;
 | 
			
		||||
import envoy.client.data.shortcuts.EnvoyShortcutConfig;
 | 
			
		||||
import envoy.client.helper.ShutdownHelper;
 | 
			
		||||
import envoy.client.net.Client;
 | 
			
		||||
import envoy.client.ui.SceneContext.SceneInfo;
 | 
			
		||||
import envoy.client.ui.controller.LoginScene;
 | 
			
		||||
import envoy.client.util.IconUtil;
 | 
			
		||||
 | 
			
		||||
@@ -94,7 +93,7 @@ public final class Startup extends Application {
 | 
			
		||||
		final var sceneContext = new SceneContext(stage);
 | 
			
		||||
		context.setSceneContext(sceneContext);
 | 
			
		||||
 | 
			
		||||
		// Authenticate with token if present
 | 
			
		||||
		// Authenticate with token if present or load login scene
 | 
			
		||||
		if (localDB.getAuthToken() != null) {
 | 
			
		||||
			logger.info("Attempting authentication with token...");
 | 
			
		||||
			localDB.loadUserData();
 | 
			
		||||
@@ -103,8 +102,9 @@ public final class Startup extends Application {
 | 
			
		||||
					VERSION, localDB.getLastSync())))
 | 
			
		||||
				sceneContext.load(SceneInfo.LOGIN_SCENE);
 | 
			
		||||
		} else
 | 
			
		||||
			// Load login scene
 | 
			
		||||
			sceneContext.load(SceneInfo.LOGIN_SCENE);
 | 
			
		||||
 | 
			
		||||
		stage.show();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -226,7 +226,7 @@ public final class Startup extends Application {
 | 
			
		||||
		// Load ChatScene
 | 
			
		||||
		stage.setMinHeight(400);
 | 
			
		||||
		stage.setMinWidth(843);
 | 
			
		||||
		context.getSceneContext().load(SceneContext.SceneInfo.CHAT_SCENE);
 | 
			
		||||
		context.getSceneContext().load(SceneInfo.CHAT_SCENE);
 | 
			
		||||
		stage.centerOnScreen();
 | 
			
		||||
 | 
			
		||||
		// Exit or minimize the stage when a close request occurs
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import envoy.util.EnvoyLog;
 | 
			
		||||
import envoy.client.data.Context;
 | 
			
		||||
import envoy.client.data.commands.*;
 | 
			
		||||
import envoy.client.helper.ShutdownHelper;
 | 
			
		||||
import envoy.client.ui.SceneContext.SceneInfo;
 | 
			
		||||
import envoy.client.ui.SceneInfo;
 | 
			
		||||
import envoy.client.ui.controller.ChatScene;
 | 
			
		||||
import envoy.client.util.*;
 | 
			
		||||
 | 
			
		||||
@@ -32,7 +32,7 @@ public final class ChatSceneCommands {
 | 
			
		||||
	private final SystemCommandBuilder	builder					=
 | 
			
		||||
		new SystemCommandBuilder(messageTextAreaCommands);
 | 
			
		||||
 | 
			
		||||
	private static final String messageDependantCommandDescription =
 | 
			
		||||
	private static final String messageDependentCommandDescription =
 | 
			
		||||
		" the given message. Use s/S to use the selected message. Otherwise expects a number relative to the uppermost completely visible message.";
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -141,7 +141,7 @@ public final class ChatSceneCommands {
 | 
			
		||||
			else
 | 
			
		||||
				useRelativeMessage(command, action, additionalCheck, positionalArgument, false);
 | 
			
		||||
		}).setDefaults("s").setNumberOfArguments(1)
 | 
			
		||||
			.setDescription(description.concat(messageDependantCommandDescription)).build(command);
 | 
			
		||||
			.setDescription(description.concat(messageDependentCommandDescription)).build(command);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void selectionNeighbor(Consumer<Message> action, Predicate<Message> additionalCheck,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
package envoy.client.ui.controller;
 | 
			
		||||
 | 
			
		||||
import static envoy.client.ui.SceneInfo.SETTINGS_SCENE;
 | 
			
		||||
 | 
			
		||||
import java.awt.Toolkit;
 | 
			
		||||
import java.awt.datatransfer.StringSelection;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
@@ -32,7 +34,7 @@ import envoy.data.*;
 | 
			
		||||
import envoy.data.Attachment.AttachmentType;
 | 
			
		||||
import envoy.data.Message.MessageStatus;
 | 
			
		||||
import envoy.event.*;
 | 
			
		||||
import envoy.event.contact.*;
 | 
			
		||||
import envoy.event.contact.UserOperation;
 | 
			
		||||
import envoy.exception.EnvoyException;
 | 
			
		||||
import envoy.util.EnvoyLog;
 | 
			
		||||
 | 
			
		||||
@@ -445,7 +447,7 @@ public final class ChatScene implements EventListener, Restorable, KeyboardMappi
 | 
			
		||||
	 */
 | 
			
		||||
	@FXML
 | 
			
		||||
	private void settingsButtonClicked() {
 | 
			
		||||
		sceneContext.load(SceneContext.SceneInfo.SETTINGS_SCENE);
 | 
			
		||||
		sceneContext.load(SETTINGS_SCENE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ import envoy.util.EnvoyLog;
 | 
			
		||||
import envoy.client.data.Context;
 | 
			
		||||
import envoy.client.event.*;
 | 
			
		||||
import envoy.client.helper.*;
 | 
			
		||||
import envoy.client.ui.SceneContext.SceneInfo;
 | 
			
		||||
import envoy.client.ui.SceneInfo;
 | 
			
		||||
import envoy.client.ui.controller.ChatScene;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,8 @@
 | 
			
		||||
 | 
			
		||||
<GridPane maxHeight="-Infinity" maxWidth="-Infinity"
 | 
			
		||||
	minHeight="400.0" minWidth="500.0"
 | 
			
		||||
	prefHeight="${screen.visualBounds.height}"
 | 
			
		||||
	prefWidth="${screen.visualBounds.width}"
 | 
			
		||||
	prefHeight="${screen.visualBounds.height}"
 | 
			
		||||
	xmlns="http://javafx.com/javafx/11.0.1"
 | 
			
		||||
	xmlns:fx="http://javafx.com/fxml/1"
 | 
			
		||||
	fx:controller="envoy.client.ui.controller.ChatScene">
 | 
			
		||||
@@ -57,8 +57,7 @@
 | 
			
		||||
					<content>
 | 
			
		||||
						<AnchorPane minHeight="0.0" minWidth="0.0">
 | 
			
		||||
							<children>
 | 
			
		||||
								<VBox prefHeight="3000.0"
 | 
			
		||||
									prefWidth="316.0">
 | 
			
		||||
								<VBox prefHeight="3000.0" prefWidth="316.0">
 | 
			
		||||
									<children>
 | 
			
		||||
										<VBox id="search-panel" maxHeight="-Infinity"
 | 
			
		||||
											minHeight="-Infinity" prefHeight="80.0" prefWidth="316.0">
 | 
			
		||||
@@ -156,8 +155,7 @@
 | 
			
		||||
						<Insets left="15.0" top="5.0" right="10.0" />
 | 
			
		||||
					</HBox.margin>
 | 
			
		||||
				</ImageView>
 | 
			
		||||
				<Region id="transparent-background"
 | 
			
		||||
					HBox.hgrow="ALWAYS" />
 | 
			
		||||
				<Region id="transparent-background" HBox.hgrow="ALWAYS" />
 | 
			
		||||
				<Button fx:id="settingsButton" mnemonicParsing="false"
 | 
			
		||||
					onAction="#settingsButtonClicked" prefHeight="30.0"
 | 
			
		||||
					prefWidth="30.0" alignment="CENTER_RIGHT">
 | 
			
		||||
 
 | 
			
		||||
@@ -7,11 +7,16 @@
 | 
			
		||||
<?import javafx.scene.layout.HBox?>
 | 
			
		||||
<?import javafx.scene.layout.VBox?>
 | 
			
		||||
 | 
			
		||||
<VBox alignment="TOP_RIGHT" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.SettingsScene">
 | 
			
		||||
<VBox alignment="TOP_RIGHT" maxHeight="-Infinity" minHeight="400.0"
 | 
			
		||||
	minWidth="500.0" xmlns="http://javafx.com/javafx/11.0.1"
 | 
			
		||||
	xmlns:fx="http://javafx.com/fxml/1"
 | 
			
		||||
	fx:controller="envoy.client.ui.controller.SettingsScene">
 | 
			
		||||
	<children>
 | 
			
		||||
		<HBox prefHeight="389.0" prefWidth="600.0">
 | 
			
		||||
			<children>
 | 
			
		||||
				<ListView id="message-list" fx:id="settingsList" onMouseClicked="#settingsListClicked" prefHeight="200.0" prefWidth="200.0">
 | 
			
		||||
				<ListView id="message-list" fx:id="settingsList"
 | 
			
		||||
					onMouseClicked="#settingsListClicked" prefHeight="200.0"
 | 
			
		||||
					prefWidth="200.0">
 | 
			
		||||
					<opaqueInsets>
 | 
			
		||||
						<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
 | 
			
		||||
					</opaqueInsets>
 | 
			
		||||
@@ -22,7 +27,8 @@
 | 
			
		||||
						<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
 | 
			
		||||
					</padding>
 | 
			
		||||
				</ListView>
 | 
			
		||||
				<TitledPane fx:id="titledPane" collapsible="false" prefHeight="400.0" prefWidth="400.0">
 | 
			
		||||
				<TitledPane fx:id="titledPane" collapsible="false"
 | 
			
		||||
					prefHeight="400.0" prefWidth="400.0">
 | 
			
		||||
					<HBox.margin>
 | 
			
		||||
						<Insets bottom="10.0" left="5.0" right="10.0" top="10.0" />
 | 
			
		||||
					</HBox.margin>
 | 
			
		||||
@@ -32,7 +38,8 @@
 | 
			
		||||
				</TitledPane>
 | 
			
		||||
			</children>
 | 
			
		||||
		</HBox>
 | 
			
		||||
		<Button defaultButton="true" mnemonicParsing="true" onMouseClicked="#backButtonClicked" text="_Back">
 | 
			
		||||
		<Button defaultButton="true" mnemonicParsing="true"
 | 
			
		||||
			onMouseClicked="#backButtonClicked" text="_Back">
 | 
			
		||||
			<opaqueInsets>
 | 
			
		||||
				<Insets />
 | 
			
		||||
			</opaqueInsets>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user
	
Wait, you don't want to log the failed loading?