From 48e150c3c3337e19b1b048f0201e17a9fc586850 Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Mon, 25 Dec 2023 18:12:24 -0500 Subject: [PATCH] Updated to use router view strategy instead. --- README.md | 11 ++-- pom.xml | 2 +- .../AnchorPaneRouterView.java | 56 +++++++++++++++++++ .../RouteChangeListener.java | 15 +++++ .../javafx_scene_router/RouterView.java | 18 ++++++ .../javafx_scene_router/SceneRouter.java | 34 ++++++----- .../SimplePaneRouterView.java | 29 ++++++++++ 7 files changed, 145 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/andrewlalis/javafx_scene_router/AnchorPaneRouterView.java create mode 100644 src/main/java/com/andrewlalis/javafx_scene_router/RouteChangeListener.java create mode 100644 src/main/java/com/andrewlalis/javafx_scene_router/RouterView.java create mode 100644 src/main/java/com/andrewlalis/javafx_scene_router/SimplePaneRouterView.java diff --git a/README.md b/README.md index 83f5dc5..cb6bb84 100644 --- a/README.md +++ b/README.md @@ -46,20 +46,23 @@ public class MyJavaFXApp extends Application { } ``` -From here, it's just a matter of attaching the router's view pane to one of +From here, it's just a matter of attaching the router's view to one of your scene's nodes, and mapping string route names to other nodes or FXML files. For example, suppose my app has a main scene with a `MainController` class. -We'd hook up the router's view pane to that scene's center view: +We'd hook up the router's view to that scene's center view, assuming you're +using an AnchorPaneRouterView for your router (the default choice). + ```java public class MainController { @FXML public BorderPane borderPane; - + @FXML public void initialize() { - borderPane.setCenter(MyJavaFXApp.router.getViewPane()); + AnchorPaneRouterView view = (AnchorPaneRouterView) MyJavaFXApp.router.getView(); + borderPane.setCenter(view.getAnchorPane()); } } ``` diff --git a/pom.xml b/pom.xml index c2b16d9..544001f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.andrewlalis javafx-scene-router - 1.3.0 + 1.4.0 JavaFX Scene Router A library that provides a router implementation for JavaFX, for browser-like navigation between pages. https://github.com/andrewlalis/javafx-scene-router diff --git a/src/main/java/com/andrewlalis/javafx_scene_router/AnchorPaneRouterView.java b/src/main/java/com/andrewlalis/javafx_scene_router/AnchorPaneRouterView.java new file mode 100644 index 0000000..cbff6d1 --- /dev/null +++ b/src/main/java/com/andrewlalis/javafx_scene_router/AnchorPaneRouterView.java @@ -0,0 +1,56 @@ +package com.andrewlalis.javafx_scene_router; + +import javafx.scene.Parent; +import javafx.scene.layout.AnchorPane; + +/** + * A router view implementation using the JavaFX {@link AnchorPane}, so that + * route contents can (optionally) be grown to fill all available space. + */ +public class AnchorPaneRouterView implements RouterView { + private final AnchorPane anchorPane = new AnchorPane(); + private final boolean expandContents; + + /** + * Constructs this router view with an explicit setting for whether to + * expand contents of the view. + * @param expandContents Whether to expand the contents of this view to + * fill all available space. + */ + public AnchorPaneRouterView(boolean expandContents) { + this.expandContents = expandContents; + } + + /** + * Constructs this router view with the default behavior of allowing route + * contents to fill all available space. + */ + public AnchorPaneRouterView() { + this(true); + } + + /** + * Shows the node in this view's anchor pane. If this view has been set to + * expand contents, then the given node will be anchored to all 4 sides of + * the anchor pane. + * @param node The node to show. + */ + @Override + public void showRouteNode(Parent node) { + if (expandContents) { + AnchorPane.setTopAnchor(node, 0.0); + AnchorPane.setRightAnchor(node, 0.0); + AnchorPane.setBottomAnchor(node, 0.0); + AnchorPane.setLeftAnchor(node, 0.0); + } + anchorPane.getChildren().setAll(node); + } + + /** + * Gets the underlying pane used for rendering. + * @return The anchor pane this view uses. + */ + public AnchorPane getAnchorPane() { + return anchorPane; + } +} diff --git a/src/main/java/com/andrewlalis/javafx_scene_router/RouteChangeListener.java b/src/main/java/com/andrewlalis/javafx_scene_router/RouteChangeListener.java new file mode 100644 index 0000000..f962b74 --- /dev/null +++ b/src/main/java/com/andrewlalis/javafx_scene_router/RouteChangeListener.java @@ -0,0 +1,15 @@ +package com.andrewlalis.javafx_scene_router; + +/** + * A listener that's invoked when a router's route is updated. + */ +public interface RouteChangeListener { + /** + * Called when a router's route changes. + * @param route The route that was navigated to. + * @param context The context at the new route. + * @param oldRoute The previous route. + * @param oldContext The context at the previous route. + */ + void routeChanged(String route, Object context, String oldRoute, Object oldContext); +} diff --git a/src/main/java/com/andrewlalis/javafx_scene_router/RouterView.java b/src/main/java/com/andrewlalis/javafx_scene_router/RouterView.java new file mode 100644 index 0000000..73014a2 --- /dev/null +++ b/src/main/java/com/andrewlalis/javafx_scene_router/RouterView.java @@ -0,0 +1,18 @@ +package com.andrewlalis.javafx_scene_router; + +import javafx.scene.Parent; + +/** + * An interface through which a router can show a route's node in the application. + *

+ * Usually, this will be implemented by adding the node to some sort of + * container, like a Pane or Stage. + *

+ */ +public interface RouterView { + /** + * Shows the node as the current one, discarding any previous route content. + * @param node The node to show. + */ + void showRouteNode(Parent node); +} diff --git a/src/main/java/com/andrewlalis/javafx_scene_router/SceneRouter.java b/src/main/java/com/andrewlalis/javafx_scene_router/SceneRouter.java index ed64432..9b91006 100644 --- a/src/main/java/com/andrewlalis/javafx_scene_router/SceneRouter.java +++ b/src/main/java/com/andrewlalis/javafx_scene_router/SceneRouter.java @@ -7,7 +7,6 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; -import javafx.scene.layout.Pane; import java.io.IOException; import java.io.UncheckedIOException; @@ -21,7 +20,7 @@ import java.util.function.Consumer; *

* 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, - * and put that node into the pre-defined pane or consumer function. + * and put that node into its configured {@link RouterView} implementation. *

*

* The router maintains a {@link RouteHistory} so that it's possible to @@ -34,11 +33,7 @@ import java.util.function.Consumer; *

*/ public class SceneRouter { - public interface RouteChangeListener { - void routeChanged(String route, Object context, String oldRoute, Object oldContext); - } - - private final Pane viewPane = new Pane(); + private final RouterView view; private final Map routeMap = new HashMap<>(); private final RouteHistory history = new RouteHistory(); private final ObservableList breadCrumbs = FXCollections.observableArrayList(); @@ -48,9 +43,19 @@ public class SceneRouter { private final Map> routeSelectionListeners = new HashMap<>(); /** - * Constructs the router. + * Constructs the router with a given router view. + * @param view The view that will display the router's current route contents. */ - public SceneRouter() {} + public SceneRouter(RouterView view) { + this.view = view; + } + + /** + * Constructs the router with a default {@link AnchorPaneRouterView}. + */ + public SceneRouter() { + this(new AnchorPaneRouterView(true)); + } /** * Maps the given route to a node, so that when the route is selected, the @@ -153,12 +158,11 @@ public class SceneRouter { } /** - * 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. + * Gets the view used by this router. + * @return The router's view. */ - public Pane getViewPane() { - return viewPane; + public RouterView getView() { + return view; } /** @@ -211,7 +215,7 @@ public class SceneRouter { * @param oldContext The context of the previous route. */ private void setCurrentNode(String route, String oldRoute, Object oldContext) { - viewPane.getChildren().setAll(getMappedNode(route)); + view.showRouteNode(getMappedNode(route)); breadCrumbs.setAll(history.getBreadCrumbs()); currentRouteProperty.set(route); for (var listener : routeChangeListeners) { diff --git a/src/main/java/com/andrewlalis/javafx_scene_router/SimplePaneRouterView.java b/src/main/java/com/andrewlalis/javafx_scene_router/SimplePaneRouterView.java new file mode 100644 index 0000000..124c8f3 --- /dev/null +++ b/src/main/java/com/andrewlalis/javafx_scene_router/SimplePaneRouterView.java @@ -0,0 +1,29 @@ +package com.andrewlalis.javafx_scene_router; + +import javafx.scene.Parent; +import javafx.scene.layout.Pane; + +/** + * A simple router view implementation that uses a JavaFX Pane, which shows + * the route contents in their preferred minimal size. + */ +public class SimplePaneRouterView implements RouterView { + private final Pane pane = new Pane(); + + /** + * Shows the node in the pane. + * @param node The node to show. + */ + @Override + public void showRouteNode(Parent node) { + pane.getChildren().setAll(node); + } + + /** + * Gets the pane that's used internally to show the contents. + * @return The pane. + */ + public Pane getPane() { + return pane; + } +}