Added replace() methods in router, added SimpleRouterView, and added RouterLink.

This commit is contained in:
Andrew Lalis 2024-01-09 20:16:56 -05:00
parent 4eb7ca6b8e
commit 43b5ca0e79
7 changed files with 154 additions and 41 deletions

View File

@ -6,7 +6,7 @@
<groupId>com.andrewlalis</groupId>
<artifactId>javafx-scene-router</artifactId>
<version>1.5.1</version>
<version>1.6.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

@ -7,8 +7,7 @@ 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();
public class AnchorPaneRouterView extends SimpleRouterView<AnchorPane> {
private final boolean expandContents;
/**
@ -18,6 +17,7 @@ public class AnchorPaneRouterView implements RouterView {
* fill all available space.
*/
public AnchorPaneRouterView(boolean expandContents) {
super(new AnchorPane());
this.expandContents = expandContents;
}
@ -43,14 +43,6 @@ public class AnchorPaneRouterView implements RouterView {
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;
super.showRouteNode(node);
}
}

View File

@ -102,6 +102,23 @@ public class SceneRouter {
return map(route, fxml, null);
}
/**
* "Warms up" the route cache by calling each route's supplier once. This
* will cause FXML resources to be loaded, such that all subsequent loads
* are much faster.
* @return A future that's complete once all routes are loaded.
*/
public CompletableFuture<Void> loadAllRoutes() {
CompletableFuture<Void> cf = new CompletableFuture<>();
Thread.ofVirtual().start(() -> {
for (Supplier<Parent> nodeSupplier : routeMap.values()) {
nodeSupplier.get();
}
cf.complete(null);
});
return cf;
}
/**
* Navigates to a given route, with a given context object.
* @param route The route to navigate to.
@ -188,6 +205,34 @@ public class SceneRouter {
return cf;
}
/**
* Navigates to the given route, clearing any previous history.
* @param route The route to navigate to.
* @param context The context for the route.
* @return A future that resolves once navigation is complete.
*/
public CompletableFuture<Void> replace(String route, Object context) {
String oldRoute = currentRouteProperty.get();
Object oldContext = history.getCurrentContext();
CompletableFuture<Void> cf = new CompletableFuture<>();
Platform.runLater(() -> {
history.clear();
history.push(route, context);
setCurrentNode(route, oldRoute, oldContext);
cf.complete(null);
});
return cf;
}
/**
* Navigates to the given route, clearing any previous history.
* @param route The route to navigate to.
* @return A future that resolves once navigation is complete.
*/
public CompletableFuture<Void> replace(String route) {
return replace(route, null);
}
/**
* Gets the context object for the current route.
* @return The context object, or null.
@ -282,6 +327,9 @@ public class SceneRouter {
if (controller instanceof RouteSelectionListener rsl) {
addRouteSelectionListener(route, rsl);
}
if (controller instanceof RouteChangeListener rcl) {
addRouteChangeListener(rcl);
}
if (controllerCustomizer != null) {
if (controller == null) throw new IllegalStateException("No controller found when loading " + resource.toString());
controllerCustomizer.accept(controller);

View File

@ -1,29 +0,0 @@
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;
}
}

View File

@ -0,0 +1,39 @@
package com.andrewlalis.javafx_scene_router;
import javafx.scene.Parent;
import javafx.scene.layout.Pane;
/**
* A simple implementation of {@link RouterView} which simply keeps a reference
* to a {@link Pane} and displays any route nodes inside that pane by setting
* its only child to the given route node.
* @param <T> The pane type.
*/
public class SimpleRouterView<T extends Pane> implements RouterView {
/**
* The pane in which route nodes are displayed.
*/
private final T pane;
/**
* Constructs this router view to use the given pane.
* @param pane The pane to use.
*/
public SimpleRouterView(T pane) {
this.pane = pane;
}
@Override
public void showRouteNode(Parent node) {
this.pane.getChildren().clear();
this.pane.getChildren().add(node);
}
/**
* Gets the pane used by this router view.
* @return The pane used by this router view.
*/
public T getPane() {
return this.pane;
}
}

View File

@ -0,0 +1,60 @@
package com.andrewlalis.javafx_scene_router.component;
import com.andrewlalis.javafx_scene_router.SceneRouter;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Hyperlink;
/**
* A hyperlink that, when clicked, navigates the user to a specified route.
*/
public class RouterLink extends Hyperlink {
@FXML
private final StringProperty routeProperty = new SimpleStringProperty(this, "route", null);
@FXML
private final ObjectProperty<SceneRouter> routerProperty = new SimpleObjectProperty<>(this, "router", null);
private Object context;
// Route property.
public StringProperty routeProperty() {
return routeProperty;
}
public final void setRoute(String route) {
this.context = null;
routeProperty.set(route);
setOnAction(event -> {
SceneRouter router = getRouter();
String currentRoute = getRoute();
if (router != null && currentRoute != null) {
router.navigate(currentRoute, context);
}
});
}
public final void setRoute(String route, Object context) {
this.context = context;
setRoute(route);
}
public final String getRoute() {
return routeProperty.get();
}
// Router property.
public ObjectProperty<SceneRouter> routerProperty() {
return routerProperty;
}
public final void setRouter(SceneRouter router) {
routerProperty.set(router);
}
public final SceneRouter getRouter() {
return routerProperty.get();
}
}

View File

@ -4,6 +4,9 @@
module com.andrewlalis.javafx_scene_router {
requires javafx.fxml;
requires javafx.graphics;
requires javafx.controls;
exports com.andrewlalis.javafx_scene_router;
exports com.andrewlalis.javafx_scene_router.component;
opens com.andrewlalis.javafx_scene_router.component to javafx.fxml;
}