Skip to content

Commit

Permalink
Refactor MobileCategoryPageBase and MobileDetailsPageBase to extend M…
Browse files Browse the repository at this point in the history
…obilePageBase

This update involves refactoring various mobile components such as MobileCategoryPageBase and MobileDetailsPageBase to inherit from a new MobilePageBase class which replaces the older SizeSupport logic. Updated MobileRouter to handle new type of MobileResponse, replaced the viewCallback() with new responseCallback() in MobileRoute. Added a new utility class MobileResponse to manage the response data from the mobile route and a new class MobilePageBase to handle all the sizing loic and also manage the swipe interactions and callbacks.
  • Loading branch information
leewyatt committed Jul 22, 2024
1 parent a4298ed commit 9dec582
Show file tree
Hide file tree
Showing 12 changed files with 382 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import com.dlsc.jfxcentral2.mobile.pages.category.MobileBlogsCategoryPage;
import com.dlsc.jfxcentral2.mobile.pages.category.MobileBooksCategoryPage;
import com.dlsc.jfxcentral2.mobile.pages.category.MobileCompaniesCategoryPage;
import com.dlsc.jfxcentral2.mobile.pages.category.MobileDocPage;
import com.dlsc.jfxcentral2.mobile.pages.category.MobileLearnJavaFXCategoryPage;
import com.dlsc.jfxcentral2.mobile.pages.category.MobileLearnMobileCategoryPage;
import com.dlsc.jfxcentral2.mobile.pages.category.MobileLearnRaspberryPiCategoryPage;
Expand All @@ -51,6 +50,7 @@
import com.dlsc.jfxcentral2.model.Size;
import com.dlsc.jfxcentral2.utils.EventBusUtil;
import com.dlsc.jfxcentral2.utils.MobileLinkUtil;
import com.dlsc.jfxcentral2.utils.MobileResponse;
import com.dlsc.jfxcentral2.utils.MobileRoute;
import com.dlsc.jfxcentral2.utils.MobileRouter;
import com.dlsc.jfxcentral2.utils.NodeUtil;
Expand Down Expand Up @@ -183,22 +183,21 @@ private void updateSizeProperty(Scene scene) {

private MobileRouter createMobileRouter() {
return MobileRouter.getInstance()
.and(MobileRoute.get(PagePath.HOME, r -> {
.and(MobileRoute.get(PagePath.HOME, url -> {
boolean repositoryUpdated = RepositoryManager.isRepositoryUpdated();
EventBusUtil.post(new RepositoryUpdatedEvent(repositoryUpdated));
if (repositoryUpdated) {
MobileHomePage mobileHomePage = MobileHomePage.getInstance();
mobileHomePage.sizeProperty().bind(size);
return mobileHomePage;
return MobileResponse.view(url, mobileHomePage);
} else {
return new MobileRefreshPage(size);
return MobileResponse.redirect(url, PagePath.REFRESH);
}
}))
.and(MobileRoute.get(PagePath.REFRESH, r -> new MobileRefreshPage(size)))
.and(MobileRoute.get(PagePath.REFRESH, r -> MobileResponse.view(r, new MobileRefreshPage(size))))
.and(MobileRoute.redirect("/index", PagePath.HOME))
.and(MobileRoute.redirect("/home", PagePath.HOME))
.and(MobileRoute.get(PagePath.LINKS, r -> new MobileLinksOfTheWeekPage(size)))
.and(MobileRoute.get(PagePath.DOCUMENTATION, r -> new MobileDocPage(size)))
.and(MobileRoute.get(PagePath.LINKS, r -> MobileResponse.view(r, new MobileLinksOfTheWeekPage(size))))
.and(createCategoryOrDetailRoute(PagePath.SHOWCASES, RealWorldApp.class, () -> new MobileShowcasesCategoryPage(size), id -> new MobileShowcaseMobileDetailsPage(size, id)))
.and(createCategoryOrDetailRoute(PagePath.REAL_WORLD, RealWorldApp.class, () -> new MobileShowcasesCategoryPage(size), id -> new MobileShowcaseMobileDetailsPage(size, id)))
.and(createCategoryOrDetailRoute(PagePath.LIBRARIES, Library.class, () -> new MobileLibrariesCategoryPage(size), id -> new MobileLibraryDetailsPage(size, id)))
Expand All @@ -221,13 +220,12 @@ private MobileRoute createCategoryOrDetailRoute(String path, Class<? extends Mod
if (index > 0 && clazz != null) {
String id = url.substring(index + 1).trim();
if (!DataRepository2.getInstance().isValidId(clazz, id)) {
return new Label("Error: 404");
return MobileResponse.view(url, new Label("Error: 404"));
}
return detailedResponse.call(id);
return MobileResponse.view(url, detailedResponse.call(id));
}
return categoryResponse.get();
return MobileResponse.view(url, categoryResponse.get());
});

}

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@
"methods":[
{"name":"<init>","parameterTypes":[] },
{"name":"main","parameterTypes":["java.lang.String[]"] },
{"name":"onRepositoryUpdated","parameterTypes":["com.dlsc.jfxcentral2.events.RepositoryUpdatedEvent"] }
{"name":"onRepositoryUpdated","parameterTypes":["com.dlsc.jfxcentral2.events.RepositoryUpdatedEvent"] },
{"name":"onOpenWebLink","parameterTypes":["com.dlsc.jfxcentral2.events.OpenWebLinkEvent"] }
]
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package com.dlsc.jfxcentral2.components;

import com.dlsc.jfxcentral2.model.Size;
import com.dlsc.jfxcentral2.utils.MobileRouter;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;

public class MobilePageBase extends VBox {

private static final String DEFAULT_STYLE_CLASS = "mobile-page-base";

/**
* Default value indicating whether swipe back is enabled.
* If enabled, the user can swipe from left to right to go back to the previous view.
*/
private static final boolean DEFAULT_SWIPE_BACK_ENABLED = true;

/**
* Default value indicating whether swipe forward is enabled.
* If enabled, the user can swipe from right to left to go forward to the next view.
*/
private static final boolean DEFAULT_SWIPE_FORWARD_ENABLED = true;

/**
* Default horizontal threshold for swipe gestures.
* If the horizontal movement is greater than this value, the swipe gesture is recognized.
*/
private static final double SWIPE_HOR_THRESHOLD = 60;

/**
* Default vertical threshold for swipe gestures.
* If the vertical movement is greater than this value, the horizontal swipe gesture is ignored.
*/
private static final double SWIPE_VERTICAL_THRESHOLD = 30;

private final MobileRouter mobileRouter = MobileRouter.getInstance();
private final SizeSupport sizeSupport = new SizeSupport(this);

private double initialX;
private double initialY;
private boolean isSwiping;

public MobilePageBase() {
getStyleClass().add(DEFAULT_STYLE_CLASS);

this.addEventFilter(MouseEvent.MOUSE_PRESSED, this::handleMousePressed);
this.addEventFilter(MouseEvent.MOUSE_RELEASED, this::handleMouseReleased);
}

private void handleMousePressed(MouseEvent event) {
initialX = event.getSceneX();
initialY = event.getSceneY();
isSwiping = true;
}

private void handleMouseReleased(MouseEvent event) {
if (!isSwiping) {
return;
}

double deltaX = event.getSceneX() - initialX;
double deltaY = event.getSceneY() - initialY;

// If the vertical movement is greater, ignore the horizontal movement.
if (Math.abs(deltaY) > SWIPE_VERTICAL_THRESHOLD) {
isSwiping = false;
return;
}

if (Math.abs(deltaX) > SWIPE_HOR_THRESHOLD) {
if (deltaX > 0 && isSwipeBackEnabled() && mobileRouter.canGoBackProperty().get()) {
onSwipeRight();
} else if (deltaX < 0 && isSwipeForwardEnabled() && mobileRouter.canGoForwardProperty().get()) {
onSwipeLeft();
}
}
isSwiping = false;
}
protected void onSwipeLeft() {
mobileRouter.goToForward();
}

protected void onSwipeRight() {
mobileRouter.goToBack();
}

// size

public final ObjectProperty<Size> sizeProperty() {
return sizeSupport.sizeProperty();
}

public final Size getSize() {
return sizeSupport.getSize();
}

public final void setSize(Size size) {
sizeSupport.setSize(size);
}

// swipe back enabled

private BooleanProperty swipeBackEnabled;

/**
* A flag that indicates whether swipe back is enabled.
* If enabled, the user can swipe from the left edge of the screen to go back to the previous view.
* If disabled, the swipe gesture is ignored.
* The default value is {@code true}.
*/
public final BooleanProperty swipeBackEnabledProperty() {
if (swipeBackEnabled == null) {
swipeBackEnabled = new SimpleBooleanProperty(this, "swipeBackEnabled", DEFAULT_SWIPE_BACK_ENABLED);
}
return swipeBackEnabled;
}

public final boolean isSwipeBackEnabled() {
return swipeBackEnabled == null ? DEFAULT_SWIPE_BACK_ENABLED : swipeBackEnabled.get();
}

public final void setSwipeBackEnabled(boolean swipeBackEnabled) {
swipeBackEnabledProperty().set(swipeBackEnabled);
}

// swipe forward enabled

private BooleanProperty swipeForwardEnabled;

/**
* A flag that indicates whether swipe forward is enabled.
* If enabled, the user can swipe from the right edge of the screen to go forward to the next view.
* If disabled, the swipe gesture is ignored.
* The default value is {@code true}.
*/
public final BooleanProperty swipeForwardEnabledProperty() {
if (swipeForwardEnabled == null) {
swipeForwardEnabled = new SimpleBooleanProperty(this, "swipeForwardEnabled", DEFAULT_SWIPE_FORWARD_ENABLED);
}
return swipeForwardEnabled;
}

public final boolean isSwipeForwardEnabled() {
return swipeForwardEnabled == null ? DEFAULT_SWIPE_FORWARD_ENABLED : swipeForwardEnabled.get();
}

public final void setSwipeForwardEnabled(boolean swipeForwardEnabled) {
swipeForwardEnabledProperty().set(swipeForwardEnabled);
}

// view will appear

private ObjectProperty<Runnable> viewWillAppear;

/**
* A callback that is invoked when the view will appear.
* This is typically called just before the view is added to the scene.
*/
public final ObjectProperty<Runnable> viewWillAppearProperty() {
if (viewWillAppear == null) {
viewWillAppear = new SimpleObjectProperty<>(this, "viewWillAppear");
}
return viewWillAppear;
}

public final Runnable getViewWillAppear() {
return viewWillAppear == null ? null : viewWillAppear.get();
}

public final void setViewWillAppear(Runnable viewWillAppear) {
viewWillAppearProperty().set(viewWillAppear);
}

// view did appear

private ObjectProperty<Runnable> viewDidAppear;

/**
* A callback that is invoked when the view appears.
* This is typically called after the view has been added to the scene.
*/
public final ObjectProperty<Runnable> viewDidAppearProperty() {
if (viewDidAppear == null) {
viewDidAppear = new SimpleObjectProperty<>(this, "viewDidAppear");
}
return viewDidAppear;
}

public final Runnable getViewDidAppear() {
return viewDidAppear == null ? null : viewDidAppear.get();
}

public final void setViewDidAppear(Runnable viewDidAppear) {
viewDidAppearProperty().set(viewDidAppear);
}

// view will disappear

private ObjectProperty<Runnable> viewWillDisappear;

/**
* A callback that is invoked when the view will disappear.
* This is typically called just before the view is removed from the scene.
*/
public final ObjectProperty<Runnable> viewWillDisappearProperty() {
if (viewWillDisappear == null) {
viewWillDisappear = new SimpleObjectProperty<>(this, "viewWillDisappear");
}
return viewWillDisappear;
}

public final Runnable getViewWillDisappear() {
return viewWillDisappear == null ? null : viewWillDisappear.get();
}

public final void setViewWillDisappear(Runnable viewWillDisappear) {
viewWillDisappearProperty().set(viewWillDisappear);
}

// view did disappear

private ObjectProperty<Runnable> viewDidDisappear;

/**
* A callback that is invoked when the view disappears.
* This is typically called after the view has been removed from the scene.
*/
public final ObjectProperty<Runnable> viewDidDisappearProperty() {
if (viewDidDisappear == null) {
viewDidDisappear = new SimpleObjectProperty<>(this, "viewDidDisappear");
}
return viewDidDisappear;
}

public final Runnable getViewDidDisappear() {
return viewDidDisappear == null ? null : viewDidDisappear.get();
}

public final void setViewDidDisappear(Runnable viewDidDisappear) {
viewDidDisappearProperty().set(viewDidDisappear);
}
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.dlsc.jfxcentral2.events;

import javafx.scene.Node;
import com.dlsc.jfxcentral2.utils.MobileResponse;

public record MobileResponseEvent(String url, Node view) {
public record MobileResponseEvent(MobileResponse mobileResponse) {
}
Loading

0 comments on commit 9dec582

Please sign in to comment.