Updated to use router view strategy instead.

This commit is contained in:
Andrew Lalis 2023-12-25 18:12:24 -05:00
parent 18ab61be28
commit 48e150c3c3
7 changed files with 145 additions and 20 deletions

View File

@ -46,12 +46,14 @@ 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
@ -59,7 +61,8 @@ public class MainController {
@FXML
public void initialize() {
borderPane.setCenter(MyJavaFXApp.router.getViewPane());
AnchorPaneRouterView view = (AnchorPaneRouterView) MyJavaFXApp.router.getView();
borderPane.setCenter(view.getAnchorPane());
}
}
```

View File

@ -6,7 +6,7 @@
<groupId>com.andrewlalis</groupId>
<artifactId>javafx-scene-router</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
<name>JavaFX Scene Router</name>
<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>

View File

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

View File

@ -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);
}

View File

@ -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.
* <p>
* Usually, this will be implemented by adding the node to some sort of
* container, like a Pane or Stage.
* </p>
*/
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);
}

View File

@ -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;
* <p>
* 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.
* </p>
* <p>
* The router maintains a {@link RouteHistory} so that it's possible to
@ -34,11 +33,7 @@ import java.util.function.Consumer;
* </p>
*/
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<String, Parent> routeMap = new HashMap<>();
private final RouteHistory history = new RouteHistory();
private final ObservableList<BreadCrumb> breadCrumbs = FXCollections.observableArrayList();
@ -48,9 +43,19 @@ public class SceneRouter {
private final Map<String, List<RouteSelectionListener>> 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) {

View File

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