diff --git a/.launchers/Install on iOS Device.run.xml b/.launchers/Install on iOS Device.run.xml new file mode 100644 index 00000000..55d0ac67 --- /dev/null +++ b/.launchers/Install on iOS Device.run.xml @@ -0,0 +1,37 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/dlsc/jfxcentral2/app/JFXCentral2MobileApp.java b/app/src/main/java/com/dlsc/jfxcentral2/app/JFXCentral2MobileApp.java index 6ec96825..710c8374 100644 --- a/app/src/main/java/com/dlsc/jfxcentral2/app/JFXCentral2MobileApp.java +++ b/app/src/main/java/com/dlsc/jfxcentral2/app/JFXCentral2MobileApp.java @@ -18,7 +18,6 @@ import com.dlsc.jfxcentral2.app.pages.MobileRefreshPage; import com.dlsc.jfxcentral2.events.OpenWebLinkEvent; import com.dlsc.jfxcentral2.events.RepositoryUpdatedEvent; -import com.dlsc.jfxcentral2.mobile.components.BottomMenuBar; import com.dlsc.jfxcentral2.mobile.components.MobileDevelopToolBar; import com.dlsc.jfxcentral2.mobile.pages.MainPage; import com.dlsc.jfxcentral2.mobile.pages.MobileHomePage; @@ -135,7 +134,7 @@ public void start(Stage stage) { scene.setFill(Color.web("#070B32")); scene.widthProperty().addListener((it -> updateSizeProperty(scene))); scene.getStylesheets().add(Objects.requireNonNull(NodeUtil.class.getResource("/com/dlsc/jfxcentral2/theme.css")).toExternalForm()); - scene.getStylesheets().add(Objects.requireNonNull(BottomMenuBar.class.getResource("/com/dlsc/jfxcentral2/mobile/mobile.css")).toExternalForm()); + scene.getStylesheets().add(Objects.requireNonNull(MainPage.class.getResource("/com/dlsc/jfxcentral2/mobile/mobile.css")).toExternalForm()); // scene.focusOwnerProperty().addListener(it -> System.out.println("focus owner: " + scene.getFocusOwner())); updateSizeProperty(scene); diff --git a/components/src/main/java/com/dlsc/jfxcentral2/components/headers/LinksOfTheWeekHeader.java b/components/src/main/java/com/dlsc/jfxcentral2/components/headers/LinksOfTheWeekHeader.java index 030b36d3..a1fe68ba 100644 --- a/components/src/main/java/com/dlsc/jfxcentral2/components/headers/LinksOfTheWeekHeader.java +++ b/components/src/main/java/com/dlsc/jfxcentral2/components/headers/LinksOfTheWeekHeader.java @@ -7,6 +7,9 @@ import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import javafx.scene.text.TextAlignment; import one.jpro.platform.routing.LinkUtil; import org.kordamp.ikonli.javafx.FontIcon; import scala.Option; @@ -36,14 +39,21 @@ public LinksOfTheWeekHeader() { CustomImageView rssImageView = new CustomImageView(); rssImageView.setImage(RSS_IMAGE); LinkUtil.setLinkInternalNoPush(rssImageView, "/lotw/rss.xml", Option.empty(), false); - //rssImageView.setVisible(false); - //rssImageView.setManaged(false); HBox box = new HBox(label, rssImageView); box.getStyleClass().add("rss-box"); box.setAlignment(Pos.CENTER); - setContent(box); + Label descriptionLabel = new Label("Do you have JavaFX news you want to share with the community? Let us know!\nSend a mail to links@jfx-central.com"); + descriptionLabel.getStyleClass().add("description-label"); + descriptionLabel.setWrapText(true); + descriptionLabel.setMinHeight(Region.USE_PREF_SIZE); + descriptionLabel.setTextAlignment(TextAlignment.CENTER); + + VBox vbox = new VBox(20, box, descriptionLabel); + vbox.setAlignment(Pos.CENTER); + + setContent(vbox); setTitle("Links of the Week"); setIkon(IkonUtil.getModelIkon(LinksOfTheWeek.class)); setBackgroundImage(BACKGROUND_IMAGE); diff --git a/components/src/main/java/module-info.java b/components/src/main/java/module-info.java index dc92c03c..a2df9fba 100644 --- a/components/src/main/java/module-info.java +++ b/components/src/main/java/module-info.java @@ -98,6 +98,7 @@ requires org.kordamp.ikonli.zondicons; requires com.rometools.rome; requires java.prefs; + requires jpro.utils.treeshowing; // ikonli icon packs END exports com.dlsc.jfxcentral2.components; diff --git a/components/src/main/resources/com/dlsc/jfxcentral2/theme.css b/components/src/main/resources/com/dlsc/jfxcentral2/theme.css index 70330225..870deb39 100644 --- a/components/src/main/resources/com/dlsc/jfxcentral2/theme.css +++ b/components/src/main/resources/com/dlsc/jfxcentral2/theme.css @@ -3273,6 +3273,11 @@ -fx-fit-height: 32px; } +.links-of-the-week-header .description-label { + -fx-padding: 20px; + -fx-text-fill: -white; +} + /** ------------------------------------ * PersonDetailHeader */ diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/BottomMenuBar.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/BottomMenuBar.java deleted file mode 100644 index 122fe7f5..00000000 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/BottomMenuBar.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.dlsc.jfxcentral2.mobile.components; - -import com.dlsc.jfxcentral.data.model.Library; -import com.dlsc.jfxcentral.data.model.LinksOfTheWeek; -import com.dlsc.jfxcentral.data.model.Person; -import com.dlsc.jfxcentral.data.model.RealWorldApp; -import com.dlsc.jfxcentral2.components.CustomToggleButton; -import com.dlsc.jfxcentral2.components.SizeSupport; -import com.dlsc.jfxcentral2.events.MobileLinkEvent; -import com.dlsc.jfxcentral2.mobile.pages.MainPage; -import com.dlsc.jfxcentral2.mobile.pages.MobileHomePage; -import com.dlsc.jfxcentral2.model.Size; -import com.dlsc.jfxcentral2.utils.EventBusUtil; -import com.dlsc.jfxcentral2.utils.IkonUtil; -import com.dlsc.jfxcentral2.utils.MobileLinkUtil; -import com.dlsc.jfxcentral2.utils.PagePath; -import com.dlsc.jfxcentral2.utils.Subscribe; -import javafx.beans.property.ObjectProperty; -import javafx.scene.control.ContentDisplay; -import javafx.scene.control.ToggleGroup; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.Region; -import org.kordamp.ikonli.javafx.FontIcon; -import org.kordamp.ikonli.materialdesign.MaterialDesign; - -public class BottomMenuBar extends HBox { - - private final SizeSupport sizeSupport = new SizeSupport(this); - private final ToggleGroup toggleGroup; - - public BottomMenuBar(Runnable closeDrawerCallback) { - getStyleClass().add("bottom-menu-bar"); - EventBusUtil.register(this); - - CustomToggleButton homeButton = new CustomToggleButton(); - homeButton.setText("Home"); - homeButton.setPrefWidth(0); - homeButton.setGraphic(new FontIcon(MaterialDesign.MDI_HOME)); - homeButton.setMaxWidth(Double.MAX_VALUE); - homeButton.setUserData(PagePath.HOME); - homeButton.setOnMousePressed(evt -> { - closeDrawerCallback.run(); - if (homeButton.isSelected()) { - // If the home page is being displayed, clicking homeButton will hide the search view and display the normal content. - MobileHomePage.getInstance().setContentType(MobileHomePage.ContentType.NORMAL); - } else { - MobileLinkUtil.getToPage(PagePath.HOME); - } - }); - HBox.setHgrow(homeButton, Priority.ALWAYS); - - CustomToggleButton linksWeekButton = new CustomToggleButton(); - linksWeekButton.setPrefWidth(0); - linksWeekButton.setText("News"); - linksWeekButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(LinksOfTheWeek.class))); - linksWeekButton.setMaxWidth(Double.MAX_VALUE); - linksWeekButton.setUserData(PagePath.LINKS); - linksWeekButton.setOnMouseClicked(evt -> closeDrawerCallback.run()); - MobileLinkUtil.setLink(linksWeekButton, PagePath.LINKS); - HBox.setHgrow(linksWeekButton, Priority.ALWAYS); - - CustomToggleButton showcasesButton = new CustomToggleButton(); - showcasesButton.setPrefWidth(0); - showcasesButton.setText("Apps"); - showcasesButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(RealWorldApp.class))); - showcasesButton.setMaxWidth(Double.MAX_VALUE); - showcasesButton.setUserData(PagePath.SHOWCASES); - showcasesButton.setOnMouseClicked(evt -> closeDrawerCallback.run()); - MobileLinkUtil.setLink(showcasesButton, PagePath.SHOWCASES); - HBox.setHgrow(showcasesButton, Priority.ALWAYS); - - CustomToggleButton libraryButton = new CustomToggleButton(); - libraryButton.setPrefWidth(0); - libraryButton.setText("Libs"); - libraryButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Library.class))); - libraryButton.setMaxWidth(Double.MAX_VALUE); - libraryButton.setUserData(PagePath.LIBRARIES); - libraryButton.setOnMouseClicked(evt -> closeDrawerCallback.run()); - MobileLinkUtil.setLink(libraryButton, PagePath.LIBRARIES); - HBox.setHgrow(libraryButton, Priority.ALWAYS); - - CustomToggleButton peopleButton = new CustomToggleButton(); - peopleButton.setPrefWidth(0); - peopleButton.setText("People"); - peopleButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Person.class))); - peopleButton.setMaxWidth(Double.MAX_VALUE); - peopleButton.setUserData(PagePath.PEOPLE); - peopleButton.setOnMouseClicked(evt -> closeDrawerCallback.run()); - MobileLinkUtil.setLink(peopleButton, PagePath.PEOPLE); - HBox.setHgrow(peopleButton, Priority.ALWAYS); - - getChildren().addAll(homeButton, linksWeekButton, showcasesButton, libraryButton, peopleButton); - - toggleGroup = new ToggleGroup(); - toggleGroup.getToggles().addAll(homeButton, linksWeekButton, showcasesButton, libraryButton, peopleButton); - - setMaxHeight(Region.USE_PREF_SIZE); - - // select home button by default - // homeButton.fire(); - } - - public final ObjectProperty sizeProperty() { - return sizeSupport.sizeProperty(); - } - - public final void setSize(Size size) { - sizeSupport.setSize(size); - } - - public final Size getSize() { - return sizeSupport.getSize(); - } - - @Subscribe - public void handleNavigation(MobileLinkEvent linkEvent) { - toggleGroup.getToggles().stream() - .filter(toggle -> toggle.getUserData().equals(linkEvent.link())) - .findFirst() - .ifPresentOrElse( - toggle -> toggle.setSelected(true), - () -> toggleGroup.selectToggle(null) - ); - } - -} \ No newline at end of file diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroPane.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroPane.java index 9e74c806..8f4a800b 100644 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroPane.java +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroPane.java @@ -24,16 +24,16 @@ public record IntroCardData(String title, String description, String imageUrl) { } public final List introCardData = new ArrayList<>(List.of( - new IntroCardData("JavaFX Books", "Explore our JavaFX book collection, from beginner guides to advanced tutorials, including game development and use-cases like JavaFX for Raspberry Pi.", "books.png"), - new IntroCardData("Videos", "Watch JavaFX videos, conference talks, demos, and tutorials for all expertise levels.", "videos.png"), - new IntroCardData("Libraries", "Explore JavaFX third-party libraries, featuring components, game engines, styles, 3D graphics, and frameworks to enhance your projects.", "libraries.png"), - new IntroCardData("JavaFX Tutorials", "Browse tutorials ranging from JavaFX basics to advanced application and game development.", "tutorials.png"), - new IntroCardData("Tools", "Explore JavaFX tools including plugins, layout, CSS tools, testing, and packaging.", "tools.png"), + new IntroCardData("Books", "Beginner guides, advanced tutorials, game development.", "books.png"), + new IntroCardData("Videos", "Watch videos of conference talks, demos, and tutorials.", "videos.png"), + new IntroCardData("Libraries", "Explore third-party libraries that you can add to your own applications.", "libraries.png"), + new IntroCardData("Tutorials", "See a listing of places where you can find good online tutorials.", "tutorials.png"), + new IntroCardData("Tools", "Find out which tools are available for styling, testing, packaging, etc...", "tools.png"), new IntroCardData("Links of The Week", "Miscellaneous stuff found on the web that is related to JavaFX.", "news.png"), - new IntroCardData("Tips & Tricks", "Discover practical JavaFX tips in this section, featuring articles that share real-world techniques and tricks for effective JavaFX development.", "tips.png"), - new IntroCardData("JavaFX Blogs", "Visit our blog section for articles from JavaFX experts, featuring practical tips, cutting-edge insights, and more from the world of JavaFX.", "blogs.png"), - new IntroCardData("People", "A curated list of people connected to JavaFX. They develop libraries, applications, tools or they present at conferences and evangelise JavaFX.", "people.png"), - new IntroCardData("Companies", "Explore companies in JavaFX, especially those with significant influence and contributions to the JavaFX community, shaping and advancing the ecosystem.", "companies.png") + new IntroCardData("Tips & Tricks", "Real-world tips and tricks for effective user interface development.", "tips.png"), + new IntroCardData("Blogs", "A collection of blogs related to JavaFX", "blogs.png"), + new IntroCardData("People", "People that influence the JavaFX ecosystem.", "people.png"), + new IntroCardData("Companies", "Companies that contribute to the JavaFX ecosystem.", "companies.png") )); public IntroPane() { diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/CategoriesPane.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/CategoriesPane.java index c4c7a7c1..105e9194 100644 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/CategoriesPane.java +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/CategoriesPane.java @@ -7,103 +7,154 @@ import com.dlsc.jfxcentral.data.model.LearnJavaFX; import com.dlsc.jfxcentral.data.model.LearnMobile; import com.dlsc.jfxcentral.data.model.LearnRaspberryPi; +import com.dlsc.jfxcentral.data.model.Library; +import com.dlsc.jfxcentral.data.model.LinksOfTheWeek; import com.dlsc.jfxcentral.data.model.Member; +import com.dlsc.jfxcentral.data.model.Person; +import com.dlsc.jfxcentral.data.model.RealWorldApp; import com.dlsc.jfxcentral.data.model.Tip; import com.dlsc.jfxcentral.data.model.Tool; import com.dlsc.jfxcentral.data.model.Tutorial; import com.dlsc.jfxcentral.data.model.Video; +import com.dlsc.jfxcentral2.components.CustomToggleButton; import com.dlsc.jfxcentral2.utils.IkonUtil; import com.dlsc.jfxcentral2.utils.MobileLinkUtil; import com.dlsc.jfxcentral2.utils.PagePath; import javafx.scene.control.Button; +import javafx.scene.control.ToggleGroup; import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.TilePane; import org.kordamp.ikonli.javafx.FontIcon; +import org.kordamp.ikonli.materialdesign.MaterialDesign; public class CategoriesPane extends GridPane { - public CategoriesPane() { + public CategoriesPane(Runnable closeDrawer) { getStyleClass().add("categories-pane"); setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); - Button booksButton = new Button(); + CustomToggleButton homeButton = new CustomToggleButton(); + homeButton.setText("Home"); + homeButton.setPrefWidth(0); + homeButton.setGraphic(new FontIcon(MaterialDesign.MDI_HOME)); + homeButton.setMaxWidth(Double.MAX_VALUE); + homeButton.setUserData(PagePath.HOME); + homeButton.setOnMousePressed(evt -> { + MobileHomePage.getInstance().setContentType(MobileHomePage.ContentType.NORMAL); + MobileLinkUtil.getToPage(PagePath.HOME); + }); + + CustomToggleButton linksWeekButton = new CustomToggleButton(); + linksWeekButton.setPrefWidth(0); + linksWeekButton.setText("News"); + linksWeekButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(LinksOfTheWeek.class))); + linksWeekButton.setMaxWidth(Double.MAX_VALUE); + linksWeekButton.setUserData(PagePath.LINKS); + linksWeekButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.LINKS)); + + CustomToggleButton showcasesButton = new CustomToggleButton(); + showcasesButton.setPrefWidth(0); + showcasesButton.setText("Apps"); + showcasesButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(RealWorldApp.class))); + showcasesButton.setMaxWidth(Double.MAX_VALUE); + showcasesButton.setUserData(PagePath.SHOWCASES); + showcasesButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.SHOWCASES)); + + CustomToggleButton libraryButton = new CustomToggleButton(); + libraryButton.setPrefWidth(0); + libraryButton.setText("Libs"); + libraryButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Library.class))); + libraryButton.setMaxWidth(Double.MAX_VALUE); + libraryButton.setUserData(PagePath.LIBRARIES); + libraryButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.LIBRARIES)); + + CustomToggleButton peopleButton = new CustomToggleButton(); + peopleButton.setPrefWidth(0); + peopleButton.setText("People"); + peopleButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Person.class))); + peopleButton.setMaxWidth(Double.MAX_VALUE); + peopleButton.setUserData(PagePath.PEOPLE); + peopleButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.PEOPLE)); + + CustomToggleButton booksButton = new CustomToggleButton(); booksButton.setText("Books"); booksButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Book.class))); booksButton.setMaxWidth(Double.MAX_VALUE); - booksButton.setUserData(PagePath.HOME); - MobileLinkUtil.setLink(booksButton, PagePath.BOOKS); + booksButton.setUserData(PagePath.BOOKS); + booksButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.BOOKS)); - Button blogsButton = new Button(); + CustomToggleButton blogsButton = new CustomToggleButton(); blogsButton.setText("Blogs"); blogsButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Blog.class))); blogsButton.setMaxWidth(Double.MAX_VALUE); blogsButton.setUserData(PagePath.BLOGS); - MobileLinkUtil.setLink(blogsButton, PagePath.BLOGS); + blogsButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.BLOGS)); - Button companiesButton = new Button(); + CustomToggleButton companiesButton = new CustomToggleButton(); companiesButton.setText("Companies"); companiesButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Company.class))); companiesButton.setMaxWidth(Double.MAX_VALUE); companiesButton.setUserData(PagePath.COMPANIES); - MobileLinkUtil.setLink(companiesButton, PagePath.COMPANIES); + companiesButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.COMPANIES)); - Button docsButton = new Button(); + CustomToggleButton docsButton = new CustomToggleButton(); docsButton.setText("Docs"); docsButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Documentation.class))); docsButton.setMaxWidth(Double.MAX_VALUE); docsButton.setUserData(PagePath.DOCUMENTATION); - MobileLinkUtil.setLink(docsButton, PagePath.DOCUMENTATION); + docsButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.DOCUMENTATION)); - Button tutorialsButton = new Button(); + CustomToggleButton tutorialsButton = new CustomToggleButton(); tutorialsButton.setText("Tutorials"); tutorialsButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Tutorial.class))); tutorialsButton.setMaxWidth(Double.MAX_VALUE); tutorialsButton.setUserData(PagePath.TUTORIALS); - MobileLinkUtil.setLink(tutorialsButton, PagePath.TUTORIALS); + tutorialsButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.TUTORIALS)); - Button tipsButton = new Button(); + CustomToggleButton tipsButton = new CustomToggleButton(); tipsButton.setText("Tips"); tipsButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Tip.class))); tipsButton.setMaxWidth(Double.MAX_VALUE); tipsButton.setUserData(PagePath.TIPS); - MobileLinkUtil.setLink(tipsButton, PagePath.TIPS); + tipsButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.LINKS)); - Button toolsButton = new Button(); + CustomToggleButton toolsButton = new CustomToggleButton(); toolsButton.setText("Tools"); toolsButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Tool.class))); toolsButton.setMaxWidth(Double.MAX_VALUE); toolsButton.setUserData(PagePath.TOOLS); - MobileLinkUtil.setLink(toolsButton, PagePath.TOOLS); + toolsButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.TOOLS)); - Button videosButton = new Button(); + CustomToggleButton videosButton = new CustomToggleButton(); videosButton.setText("Videos"); videosButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(Video.class))); videosButton.setMaxWidth(Double.MAX_VALUE); videosButton.setUserData(PagePath.VIDEOS); - MobileLinkUtil.setLink(videosButton, PagePath.VIDEOS); + videosButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.VIDEOS)); - Button learnJavaFXButton = new Button(); + CustomToggleButton learnJavaFXButton = new CustomToggleButton(); learnJavaFXButton.setText("Learn JFX"); learnJavaFXButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(LearnJavaFX.class))); learnJavaFXButton.setMaxWidth(Double.MAX_VALUE); learnJavaFXButton.setUserData(PagePath.LEARN_JAVAFX); - MobileLinkUtil.setLink(learnJavaFXButton, PagePath.LEARN_JAVAFX); + learnJavaFXButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.LEARN_JAVAFX)); - Button learnMobileButton = new Button(); + CustomToggleButton learnMobileButton = new CustomToggleButton(); learnMobileButton.setText("Learn Mobile"); learnMobileButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(LearnMobile.class))); learnMobileButton.setMaxWidth(Double.MAX_VALUE); learnMobileButton.setUserData(PagePath.LEARN_MOBILE); - MobileLinkUtil.setLink(learnMobileButton, PagePath.LEARN_MOBILE); + learnMobileButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.LEARN_MOBILE)); - Button learnRaspberryPiButton = new Button(); + CustomToggleButton learnRaspberryPiButton = new CustomToggleButton(); learnRaspberryPiButton.setText("Learn PI"); learnRaspberryPiButton.setGraphic(new FontIcon(IkonUtil.getModelIkon(LearnRaspberryPi.class))); learnRaspberryPiButton.setMaxWidth(Double.MAX_VALUE); learnRaspberryPiButton.setUserData(PagePath.LEARN_RASPBERRYPI); - MobileLinkUtil.setLink(learnRaspberryPiButton, PagePath.LEARN_RASPBERRYPI); + learnRaspberryPiButton.setOnMousePressed(evt -> MobileLinkUtil.getToPage(PagePath.LEARN_RASPBERRYPI)); GridPane.setHgrow(videosButton, Priority.ALWAYS); GridPane.setHgrow(toolsButton, Priority.ALWAYS); @@ -141,18 +192,34 @@ public CategoriesPane() { learnMobileButton.setPrefWidth(0); learnRaspberryPiButton.setPrefWidth(0); - add(videosButton, 0, 0); - add(toolsButton, 1, 0); - add(docsButton, 2, 0); - add(tipsButton, 3, 0); - add(tutorialsButton, 4, 0); - - add(learnJavaFXButton, 0, 1); - add(learnRaspberryPiButton, 1, 1); - add(learnMobileButton, 2, 1); - add(booksButton, 3, 1); - add(blogsButton, 4, 1); - - add(companiesButton, 0, 2); + add(homeButton, 0, 0); + add(linksWeekButton, 1, 0); + add(showcasesButton, 2, 0); + add(libraryButton, 3, 0); + add(peopleButton, 4, 0); + + add(videosButton, 0, 1); + add(toolsButton, 1, 1); + add(docsButton, 2, 1); + add(tipsButton, 3, 1); + add(tutorialsButton, 4, 1); + + add(learnJavaFXButton, 0, 2); + add(learnRaspberryPiButton, 1, 2); + add(learnMobileButton, 2, 2); + add(booksButton, 3, 2); + add(blogsButton, 4, 2); + + add(companiesButton, 0, 3); + + ToggleGroup toggleGroup = new ToggleGroup(); + toggleGroup.getToggles().addAll( + homeButton, linksWeekButton, showcasesButton, libraryButton, peopleButton, + videosButton, toolsButton, docsButton, tipsButton, tutorialsButton, + learnJavaFXButton, learnRaspberryPiButton, learnMobileButton, booksButton, blogsButton + ); + + toggleGroup.selectToggle(homeButton); +// toggleGroup.selectedToggleProperty().addListener(it -> closeDrawer.run()); } } \ No newline at end of file diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/MobileHomePage.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/MobileHomePage.java index a359e7cc..4ec17809 100644 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/MobileHomePage.java +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/pages/MobileHomePage.java @@ -124,12 +124,6 @@ private Node createNormalView() { LearnCategoryBox learnCategoryBox = new LearnCategoryBox(); - List linksOfTheWeek = DataRepository2.getInstance().getLinksOfTheWeek(); - - WeekLinksView weekLinksView = new WeekLinksView(); - weekLinksView.sizeProperty().bind(sizeProperty()); - weekLinksView.setLinksOfTheWeek(linksOfTheWeek.get(linksOfTheWeek.size() - 1)); - List randomApps = getRandomSample(DataRepository2.getInstance().getRealWorldApps(), 3); CategoryPreviewView showCasePreviewView = CategoryPreviewView.createShowCasePreviewView(randomApps, PagePath.SHOWCASES); showCasePreviewView.sizeProperty().bind(sizeProperty()); @@ -158,7 +152,6 @@ private Node createNormalView() { CategoryPreviewView blogPreviewView = CategoryPreviewView.createBlogPreviewView(randomBlogs, PagePath.BLOGS); blogPreviewView.sizeProperty().bind(sizeProperty()); - // VBox normalView = new VBox(categoryAdvancedView, weekLinksView, showCasePreviewView, peoplePreviewView, libraryPreviewView, booksPreviewView, videoPreviewView, blogPreviewView, tipsPreviewView, learnCategoryBox); VBox normalView = new VBox(showCasePreviewView, peoplePreviewView, libraryPreviewView, booksPreviewView, videoPreviewView, blogPreviewView, tipsPreviewView, learnCategoryBox); normalView.getStyleClass().add("content-box"); diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/skin/MainPageSkin.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/skin/MainPageSkin.java index 2ea1181d..12133236 100644 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/skin/MainPageSkin.java +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/skin/MainPageSkin.java @@ -4,7 +4,6 @@ import com.dlsc.jfxcentral2.components.MobilePageBase; import com.dlsc.jfxcentral2.events.MobileResponseEvent; import com.dlsc.jfxcentral2.events.RepositoryUpdatedEvent; -import com.dlsc.jfxcentral2.mobile.components.BottomMenuBar; import com.dlsc.jfxcentral2.mobile.pages.CategoriesPane; import com.dlsc.jfxcentral2.mobile.pages.MainPage; import com.dlsc.jfxcentral2.mobile.utils.PreferredFocusedNodeProvider; @@ -18,7 +17,6 @@ import javafx.beans.property.SimpleDoubleProperty; import javafx.geometry.Pos; import javafx.scene.Node; -import javafx.scene.control.Label; import javafx.scene.control.SkinBase; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; @@ -34,49 +32,53 @@ public class MainPageSkin extends SkinBase { - private final BottomMenuBar bottomMenuBar; + public static final double CLOSED_DRAWER_HEIGHT = .28; + public static final int DRAWER_ANIMATION_DURATION = 150; + private final StackPane contentPane = new StackPane(); private final GlassPane glassPane = new GlassPane(); private final Node drawer; private StackPane drawerHandle; - private final DoubleProperty drawerHeightPercentage = new SimpleDoubleProperty(); + // value between 0 and 1 + private final DoubleProperty drawerHeight = new SimpleDoubleProperty(CLOSED_DRAWER_HEIGHT); + private CategoriesPane content; private Timeline timeline; + private double startY = -1; public MainPageSkin(MainPage control) { super(control); EventBusUtil.register(this); - bottomMenuBar = new BottomMenuBar(() -> hideDrawer()); - bottomMenuBar.setVisible(false); - drawer = createDrawerContent(); contentPane.getStyleClass().add("content-pane"); contentPane.setManaged(false); - bottomMenuBar.setManaged(false); glassPane.setManaged(false); drawer.setManaged(false); + drawer.setVisible(false); glassPane.setOnMouseClicked(evt -> hideDrawer()); - glassPane.hideProperty().bind(drawerHeightPercentage.isEqualTo(0)); + glassPane.setBlockingOpacity(0); + glassPane.hideProperty().bind(drawerHeight.lessThanOrEqualTo(CLOSED_DRAWER_HEIGHT)); - getChildren().setAll(contentPane, bottomMenuBar, glassPane, drawer); + getChildren().setAll(contentPane, glassPane, drawer); - drawerHeightPercentage.addListener(it -> getSkinnable().requestLayout()); + drawerHeight.addListener(it -> getSkinnable().requestLayout()); } @Override protected void layoutChildren(double contentX, double contentY, double contentWidth, double contentHeight) { - double barHeight = bottomMenuBar.prefHeight(contentWidth); - bottomMenuBar.resizeRelocate(contentX, contentY + contentHeight - barHeight, contentWidth, barHeight); - double drawerHeight = drawerHeightPercentage.get() * content.prefHeight(-1) + drawerHandle.prefHeight(-1); - drawer.resizeRelocate(contentX, contentY + contentHeight - barHeight - drawerHeight, contentWidth, drawerHeight); - contentPane.resizeRelocate(contentX, contentY, contentWidth, contentHeight - barHeight - drawerHeight); - glassPane.resizeRelocate(contentX, contentY, contentWidth, contentHeight - barHeight - drawerHeight); + double drawerHeight = 0; + if (drawer.isVisible()) { + drawerHeight = this.drawerHeight.get() * content.prefHeight(-1) + drawerHandle.prefHeight(-1); + drawer.resizeRelocate(contentX, contentY + contentHeight - drawerHeight, contentWidth, drawerHeight); + } + contentPane.resizeRelocate(contentX, contentY, contentWidth, contentHeight - drawerHeight); + glassPane.resizeRelocate(contentX, contentY, contentWidth, contentHeight - drawerHeight); } private Node createDrawerContent() { @@ -90,15 +92,8 @@ private Node createDrawerContent() { drawerHandle.setMaxWidth(Double.MAX_VALUE); drawerHandle.setMinHeight(Region.USE_PREF_SIZE); drawerHandle.getStyleClass().add("handle"); - drawerHandle.setOnMouseClicked(evt -> { - if (drawerHeightPercentage.get() > 0) { - hideDrawer(); - } else { - showDrawer(); - } - }); - content = new CategoriesPane(); + content = new CategoriesPane(this::hideDrawer); content.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); content.setAlignment(Pos.CENTER); content.setMouseTransparent(false); @@ -116,19 +111,61 @@ private Node createDrawerContent() { clip.setLayoutY(-50); drawer.setClip(clip); + drawer.addEventFilter(MouseEvent.MOUSE_PRESSED, evt -> startY = evt.getScreenY()); + + drawer.addEventFilter(MouseEvent.MOUSE_RELEASED, evt -> { + startY = 0; + + if (drawerHeight.get() > CLOSED_DRAWER_HEIGHT) { + if (drawerHeight.get() < .75) { + hideDrawer(); + } else { + showDrawer(); + } + } + }); + + drawer.addEventFilter(MouseEvent.MOUSE_DRAGGED, evt -> { + if (startY != -1) { + double deltaY = startY - evt.getScreenY(); + double height = drawerHeight.get(); + height += (deltaY / drawer.prefHeight(-1)); + if (height > CLOSED_DRAWER_HEIGHT && height <= 1) { + height = Math.max(CLOSED_DRAWER_HEIGHT, Math.min(1, height)); + drawerHeight.set(height); + startY = evt.getScreenY(); + } + } + }); + +// drawer.addEventFilter(MouseEvent.MOUSE_CLICKED, evt -> { +// if (evt.isConsumed()) { +// return; +// } +// if (drawerHeight.get() > CLOSED_DRAWER_HEIGHT) { +// hideDrawer(); +// } else if (evt.getClickCount() == 2) { +// showDrawer(); +// } +// }); + + drawer.setOnSwipeDown(evt -> hideDrawer()); + drawer.setOnSwipeUp(evt -> showDrawer()); + return drawer; } private void installCloseDrawerHandler(Node node) { - node.addEventFilter(MouseEvent.MOUSE_CLICKED, evt -> { - if (evt.getButton().equals(MouseButton.PRIMARY) && evt.isStillSincePress()) { - hideDrawer(); - } - }); +// node.addEventFilter(MouseEvent.MOUSE_CLICKED, evt -> { +// if (evt.getButton().equals(MouseButton.PRIMARY) && evt.isStillSincePress()) { +// System.out.println("closing bc of handler"); +// hideDrawer(); +// } +// }); } private void hideDrawer() { - animateDrawer(0); + animateDrawer(CLOSED_DRAWER_HEIGHT); } private void showDrawer() { @@ -140,8 +177,8 @@ private void animateDrawer(double value) { timeline.stop(); } - KeyValue keyValue = new KeyValue(drawerHeightPercentage, value); - KeyFrame keyFrame = new KeyFrame(Duration.millis(100), keyValue); + KeyValue keyValue = new KeyValue(drawerHeight, value); + KeyFrame keyFrame = new KeyFrame(Duration.millis(DRAWER_ANIMATION_DURATION), keyValue); timeline = new Timeline(keyFrame); timeline.play(); } @@ -185,7 +222,6 @@ private void invokeLifecycleMethod(Node view, Function @Subscribe public void onHideMenuBarEvent(RepositoryUpdatedEvent event) { - bottomMenuBar.setVisible(event.isUpdated()); + drawer.setVisible(event.isUpdated()); } - } diff --git a/mobile/src/main/resources/com/dlsc/jfxcentral2/mobile/mobile.css b/mobile/src/main/resources/com/dlsc/jfxcentral2/mobile/mobile.css index 20a0eb31..16d62288 100644 --- a/mobile/src/main/resources/com/dlsc/jfxcentral2/mobile/mobile.css +++ b/mobile/src/main/resources/com/dlsc/jfxcentral2/mobile/mobile.css @@ -6,7 +6,7 @@ } /** ---------------------------------- - *PrettyScrollPane + * PrettyScrollPane */ .scroll-pane.mobile { -fx-fit-to-width: true; @@ -16,43 +16,6 @@ -fx-background-color: -white; } -/** ---------------------------------- - * BottomMenuBar - */ -.bottom-menu-bar { - -fx-alignment: top-center; - -fx-background-color: -background; - -fx-padding: 8px 0 25px 0; - -fx-border-color: -grey-10; - -fx-border-width: 1 0 0 0; - -fx-font-size: 12px; -} - -.bottom-menu-bar .toggle-button { - -fx-content-display: top; - -fx-background-color: transparent; - -fx-text-fill: -grey-60; - -fx-padding: 0 0 5px 0; - -fx-graphic-text-gap: 0px; -} - -.bottom-menu-bar .toggle-button .ikonli-font-icon { - -fx-icon-size: 24px; - -fx-icon-color: -grey-60; -} - -.bottom-menu-bar:md-lg .toggle-button .ikonli-font-icon { - -fx-icon-size: 24px; -} - -.bottom-menu-bar .toggle-button:selected { - -fx-text-fill: -bright-blue; -} - -.bottom-menu-bar .toggle-button:selected .ikonli-font-icon { - -fx-icon-color: -bright-blue; -} - /** ---------------------------------- * BackButton */ @@ -575,9 +538,10 @@ .main-page .drawer > .categories-pane { -fx-font-size: 12px; + -fx-padding: 0px 0px 15px 0px; } -.main-page .drawer > .categories-pane > .button { +.main-page .drawer > .categories-pane > .toggle-button { -fx-content-display: top; -fx-background-color: transparent; -fx-text-fill: -grey-60; @@ -585,11 +549,19 @@ -fx-graphic-text-gap: 0px; } -.main-page .drawer > .categories-pane > .button .ikonli-font-icon { +.main-page .drawer > .categories-pane > .toggle-button .ikonli-font-icon { -fx-icon-size: 24px; -fx-icon-color: -grey-60; } +.main-page .drawer > .categories-pane > .toggle-button:selected { + -fx-text-fill: -bright-blue; +} + +.main-page .drawer > .categories-pane > .toggle-button:selected .ikonli-font-icon { + -fx-icon-color: -bright-blue; +} + /** ---------------------------------- * MobileSearchTextField */ diff --git a/pom.xml b/pom.xml index c4c6c110..c0d71682 100644 --- a/pom.xml +++ b/pom.xml @@ -278,7 +278,7 @@ com.dlsc.gemsfx gemsfx - 2.23.0 + 2.47.0 diff --git a/sampler/src/main/java/com/dlsc/jfxcentral2/demo/JFXCentralSampleBase.java b/sampler/src/main/java/com/dlsc/jfxcentral2/demo/JFXCentralSampleBase.java index d037ccd4..1904a946 100644 --- a/sampler/src/main/java/com/dlsc/jfxcentral2/demo/JFXCentralSampleBase.java +++ b/sampler/src/main/java/com/dlsc/jfxcentral2/demo/JFXCentralSampleBase.java @@ -5,7 +5,7 @@ */ package com.dlsc.jfxcentral2.demo; -import com.dlsc.jfxcentral2.mobile.components.BottomMenuBar; +import com.dlsc.jfxcentral2.mobile.pages.MainPage; import com.dlsc.jfxcentral2.utils.NodeUtil; import fr.brouillard.oss.cssfx.CSSFX; import fxsampler.SampleBase; @@ -18,6 +18,8 @@ import javafx.scene.layout.VBox; import javafx.stage.Stage; +import java.util.Objects; + public abstract class JFXCentralSampleBase extends SampleBase { private boolean stylesheetsAdded; @@ -56,10 +58,9 @@ public final Node getPanel(Stage stage) { } - scene.getStylesheets().add(NodeUtil.class.getResource("/com/dlsc/jfxcentral2/theme.css").toExternalForm()); - scene.getStylesheets().add(BottomMenuBar.class.getResource("/com/dlsc/jfxcentral2/mobile/mobile.css").toExternalForm()); - - scene.getStylesheets().add(JFXCentralSampleBase.class.getResource("/com/dlsc/jfxcentral2/demo/components/test.css").toExternalForm()); + scene.getStylesheets().add(Objects.requireNonNull(NodeUtil.class.getResource("/com/dlsc/jfxcentral2/theme.css")).toExternalForm()); + scene.getStylesheets().add(Objects.requireNonNull(MainPage.class.getResource("/com/dlsc/jfxcentral2/mobile/mobile.css")).toExternalForm()); + scene.getStylesheets().add(Objects.requireNonNull(JFXCentralSampleBase.class.getResource("/com/dlsc/jfxcentral2/demo/components/test.css")).toExternalForm()); stylesheetsAdded = true; }); diff --git a/sampler/src/main/java/com/dlsc/jfxcentral2/demo/mobile/HelloBottomMenuBar.java b/sampler/src/main/java/com/dlsc/jfxcentral2/demo/mobile/HelloBottomMenuBar.java deleted file mode 100644 index 5d77e8db..00000000 --- a/sampler/src/main/java/com/dlsc/jfxcentral2/demo/mobile/HelloBottomMenuBar.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dlsc.jfxcentral2.demo.mobile; - -import com.dlsc.jfxcentral2.components.SizeComboBox; -import com.dlsc.jfxcentral2.demo.JFXCentralSampleBase; -import com.dlsc.jfxcentral2.mobile.components.BottomMenuBar; -import javafx.scene.Node; -import javafx.scene.layout.Region; -import javafx.scene.layout.StackPane; - -public class HelloBottomMenuBar extends JFXCentralSampleBase { - - private BottomMenuBar bottomMenuBar; - - @Override - protected Region createControl() { - bottomMenuBar = new BottomMenuBar(); - return new StackPane(bottomMenuBar); - } - - @Override - public Node getControlPanel() { - SizeComboBox sizeComboBox = new SizeComboBox(); - bottomMenuBar.sizeProperty().bind(sizeComboBox.sizeProperty()); - return sizeComboBox; - } - - @Override - public String getSampleName() { - return "BottomMenuBar"; - } -}