Updated scene router structure to use internal pane and v1.1.0

This commit is contained in:
Andrew Lalis 2023-12-22 11:53:30 -05:00
parent 04480b9da4
commit bddea200fc
2 changed files with 27 additions and 29 deletions

View File

@ -6,7 +6,7 @@
<groupId>com.andrewlalis</groupId> <groupId>com.andrewlalis</groupId>
<artifactId>javafx-scene-router</artifactId> <artifactId>javafx-scene-router</artifactId>
<version>1.0.0</version> <version>1.1.0</version>
<name>JavaFX Scene Router</name> <name>JavaFX Scene Router</name>
<description>A library that provides a router implementation for JavaFX, for browser-like navigation between pages.</description> <description>A library that provides a router implementation for JavaFX, for browser-like navigation between pages.</description>
<url>https://github.com/andrewlalis/javafx-scene-router</url> <url>https://github.com/andrewlalis/javafx-scene-router</url>

View File

@ -7,14 +7,14 @@ import javafx.scene.layout.Pane;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
* A router that shows different content in a pane depending on which route is * A router that shows different content in a pane depending on which route is
* selected. Each router must be initialized with a JavaFX pane, or a consumer * selected.
* function that's called to set the content each time a new route is selected.
* <p> * <p>
* The router has a mapping of "routes" (think, Strings) to JavaFX Parent * The router has a mapping of "routes" (think, Strings) to JavaFX Parent
* nodes. When a route is selected, the router will lookup the mapped node, * nodes. When a route is selected, the router will lookup the mapped node,
@ -26,29 +26,14 @@ import java.util.function.Consumer;
* </p> * </p>
*/ */
public class SceneRouter { public class SceneRouter {
private final Consumer<Parent> setter; private final Pane viewPane = new Pane();
private final Map<String, Parent> routeMap = new HashMap<>(); private final Map<String, Parent> routeMap = new HashMap<>();
private final RouteHistory history = new RouteHistory(); private final RouteHistory history = new RouteHistory();
/** /**
* Constructs the router to show route content in the given pane. * Constructs the router.
* @param pane The pane to show route content in.
*/ */
public SceneRouter(Pane pane) { public SceneRouter() {}
this(p -> pane.getChildren().setAll(p));
}
/**
* Constructs the router to supply route content to the given consumer, so
* that it may place the content somewhere. For example, you might like to
* use this if you'd like to have a router place content in the center of a
* {@link javafx.scene.layout.BorderPane}, like so:
* <p><code>var router = new SceneRouter(myBorderPane::setCenter);</code></p>
* @param setter The consumer that is supplied route content to show.
*/
public SceneRouter(Consumer<Parent> setter) {
this.setter = setter;
}
/** /**
* Maps the given route to a node, so that when the route is selected, the * Maps the given route to a node, so that when the route is selected, the
@ -71,7 +56,7 @@ public class SceneRouter {
* may be null. * may be null.
* @return This router. * @return This router.
*/ */
public SceneRouter map(String route, String fxml, Consumer<?> controllerCustomizer) { public SceneRouter map(String route, URL fxml, Consumer<?> controllerCustomizer) {
return map(route, loadNode(fxml, controllerCustomizer)); return map(route, loadNode(fxml, controllerCustomizer));
} }
@ -81,7 +66,7 @@ public class SceneRouter {
* @param fxml The FXML classpath resource to load from. * @param fxml The FXML classpath resource to load from.
* @return This router. * @return This router.
*/ */
public SceneRouter map(String route, String fxml) { public SceneRouter map(String route, URL fxml) {
return map(route, fxml, null); return map(route, fxml, null);
} }
@ -93,7 +78,7 @@ public class SceneRouter {
public void navigate(String route, Object context) { public void navigate(String route, Object context) {
Platform.runLater(() -> { Platform.runLater(() -> {
history.push(route, context); history.push(route, context);
setter.accept(getMappedNode(route)); setCurrentNode(getMappedNode(route));
}); });
} }
@ -110,7 +95,7 @@ public class SceneRouter {
*/ */
public void navigateBack() { public void navigateBack() {
Platform.runLater(() -> history.back() Platform.runLater(() -> history.back()
.ifPresent(prev -> setter.accept(getMappedNode(prev.route()))) .ifPresent(prev -> setCurrentNode(getMappedNode(prev.route())))
); );
} }
@ -119,7 +104,7 @@ public class SceneRouter {
*/ */
public void navigateForward() { public void navigateForward() {
Platform.runLater(() -> history.forward() Platform.runLater(() -> history.forward()
.ifPresent(next -> setter.accept(getMappedNode(next.route()))) .ifPresent(next -> setCurrentNode(getMappedNode(next.route())))
); );
} }
@ -140,19 +125,32 @@ public class SceneRouter {
return history; return history;
} }
/**
* Gets the view pane that this router renders to. Take this and put it
* somewhere in your view's hierarchy to show the router's content.
* @return The router's view pane.
*/
public Pane getViewPane() {
return viewPane;
}
private Parent getMappedNode(String route) { private Parent getMappedNode(String route) {
Parent node = routeMap.get(route); Parent node = routeMap.get(route);
if (node == null) throw new IllegalArgumentException("Route " + route + " is not mapped to any node."); if (node == null) throw new IllegalArgumentException("Route " + route + " is not mapped to any node.");
return node; return node;
} }
private <T> Parent loadNode(String fxml, Consumer<T> controllerCustomizer) { private void setCurrentNode(Parent node) {
FXMLLoader loader = new FXMLLoader(SceneRouter.class.getResource(fxml)); viewPane.getChildren().setAll(node);
}
private <T> Parent loadNode(URL resource, Consumer<T> controllerCustomizer) {
FXMLLoader loader = new FXMLLoader(resource);
try { try {
Parent p = loader.load(); Parent p = loader.load();
if (controllerCustomizer != null) { if (controllerCustomizer != null) {
T controller = loader.getController(); T controller = loader.getController();
if (controller == null) throw new IllegalStateException("No controller found when loading " + fxml); if (controller == null) throw new IllegalStateException("No controller found when loading " + resource.toString());
controllerCustomizer.accept(controller); controllerCustomizer.accept(controller);
} }
return p; return p;