diff --git a/app/src/main/java/com/dlsc/jfxcentral2/app/pages/MobileRefreshPage.java b/app/src/main/java/com/dlsc/jfxcentral2/app/pages/MobileRefreshPage.java index 5eec727d..4d7b6a49 100644 --- a/app/src/main/java/com/dlsc/jfxcentral2/app/pages/MobileRefreshPage.java +++ b/app/src/main/java/com/dlsc/jfxcentral2/app/pages/MobileRefreshPage.java @@ -3,7 +3,7 @@ import com.dlsc.jfxcentral2.app.RepositoryManager; import com.dlsc.jfxcentral2.app.utils.RepositoryUpdater; import com.dlsc.jfxcentral2.components.CustomImageView; -import com.dlsc.jfxcentral2.mobile.components.WelcomePageView; +import com.dlsc.jfxcentral2.mobile.components.IntroPane; import com.dlsc.jfxcentral2.model.Size; import com.dlsc.jfxcentral2.utils.MobileLinkUtil; import com.dlsc.jfxcentral2.utils.PagePath; @@ -44,12 +44,15 @@ public MobileRefreshPage(ObjectProperty size) { invalidationListener.invalidated(null); }); - // top part - WelcomePageView welcomePageView = new WelcomePageView(); - StackPane topBox = new StackPane(welcomePageView); - topBox.getStyleClass().add("top-box"); + // top part (logo) + CustomImageView logo = new CustomImageView(); + logo.getStyleClass().addAll("jfx-central-logo", "color"); - Label loadLabel = new Label("Progress download github repository. 38%"); + // center part (intro pane) + IntroPane introPane = new IntroPane(); + VBox.setVgrow(introPane, Priority.ALWAYS); + + Label loadLabel = new Label(); loadLabel.getStyleClass().add("load-label"); loadLabel.setManaged(false); loadLabel.setVisible(false); @@ -79,24 +82,10 @@ public MobileRefreshPage(ObjectProperty size) { repositoryUpdater.performUpdate(false); }); - Label welcomeLabel = new Label("Welcome to JFXCentral"); - welcomeLabel.getStyleClass().add("welcome-label"); - welcomeLabel.managedProperty().bind(welcomeLabel.visibleProperty()); - welcomeLabel.visibleProperty().bind(startButton.visibleProperty().not()); - - Label descLabel = new Label("Home to anything related to JavaFX."); - descLabel.getStyleClass().add("desc-label"); - descLabel.managedProperty().bind(descLabel.visibleProperty()); - descLabel.visibleProperty().bind(startButton.visibleProperty().not()); - - VBox bottomBox = new VBox(welcomeLabel, descLabel, startButton, loadLabel); + VBox bottomBox = new VBox(startButton, loadLabel); bottomBox.getStyleClass().add("bottom-box"); - VBox.setVgrow(bottomBox, Priority.ALWAYS); - - CustomImageView logo = new CustomImageView(); - logo.getStyleClass().addAll("jfx-central-logo", "color"); - VBox content = new VBox(topBox, bottomBox, logo); + VBox content = new VBox(logo, introPane, bottomBox); content.getStyleClass().add("content-box"); getChildren().add(content); diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/WelcomePageCell.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroCard.java similarity index 93% rename from mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/WelcomePageCell.java rename to mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroCard.java index 01b0568d..3b867865 100644 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/WelcomePageCell.java +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroCard.java @@ -8,11 +8,11 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -public class WelcomePageCell extends VBox { +public class IntroCard extends VBox { - private static final String DEFAULT_STYLE_CLASS = "welcome-page-view-cell"; + private static final String DEFAULT_STYLE_CLASS = "intro-card"; - public WelcomePageCell() { + public IntroCard() { getStyleClass().add(DEFAULT_STYLE_CLASS); CustomImageView imageView = new CustomImageView(); 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 new file mode 100644 index 00000000..9e74c806 --- /dev/null +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/IntroPane.java @@ -0,0 +1,95 @@ +package com.dlsc.jfxcentral2.mobile.components; + +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; +import javafx.util.Duration; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class IntroPane extends VBox { + + private static final String DEFAULT_STYLE_CLASS = "intro-pane"; + public static final String DOT = "dot"; + public static final String SELECTED = "selected"; + private final PageView pageView; + + 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("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") + )); + + public IntroPane() { + getStyleClass().add(DEFAULT_STYLE_CLASS); + + // shuffle pages + Collections.shuffle(introCardData); + + // page view + pageView = new PageView(); + pageView.setSwitchPageDuration(Duration.seconds(0.5)); + pageView.setPageFactory(pageIndex -> { + int index = pageIndex % introCardData.size(); + + IntroCardData cardData = introCardData.get(index); + IntroCard cell = new IntroCard(); + cell.getStyleClass().add(cardData.title().toLowerCase().replace(" ", "-")); + URL resource = IntroPane.class.getResource(cardData.imageUrl()); + cell.setImage(new Image(Objects.requireNonNull(resource).toExternalForm())); + cell.setTitle(cardData.title()); + cell.setDescription(cardData.description()); + + return cell; + }); + pageView.setCurrentPageIndex(0); + HBox progressBox = createProgressBox(); + + VBox.setVgrow(pageView, Priority.ALWAYS); + getChildren().addAll(pageView, progressBox); + } + + private HBox createProgressBox() { + List dots = new ArrayList<>(); + for (int i = 0; i < introCardData.size(); i++) { + Region dot = new Region(); + dot.getStyleClass().add(DOT); + int finalI = i; + dot.setOnMousePressed(evt -> pageView.setCurrentPageIndex(finalI)); + dots.add(dot); + } + + dots.get(0).getStyleClass().add(SELECTED); + + pageView.currentPageIndexProperty().addListener((obs, oldPage, newPage) -> { + int oldIndex = oldPage.intValue() % introCardData.size(); + int newIndex = newPage.intValue() % introCardData.size(); + + dots.get(oldIndex).getStyleClass().remove(SELECTED); + dots.get(newIndex).getStyleClass().add(SELECTED); + }); + + HBox dotBox = new HBox(); + dotBox.getStyleClass().add("dot-box"); + dotBox.getChildren().addAll(dots); + + return dotBox; + } + +} diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LearnListCell.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LearnListCell.java index 5af713db..9465e8b6 100644 --- a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LearnListCell.java +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LearnListCell.java @@ -47,6 +47,7 @@ protected void updateItem(Learn item, boolean empty) { .ifPresent(person -> { AvatarView avatarView = new AvatarView(); avatarView.setTooltip(new Tooltip(person.getName())); + avatarView.setMouseTransparent(true); avatarView.imageProperty().bind(ImageManager.getInstance().personImageProperty(person)); authorBox.getChildren().add(avatarView); })); diff --git a/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LinkedObjectsBox.java b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LinkedObjectsBox.java new file mode 100644 index 00000000..a561720f --- /dev/null +++ b/mobile/src/main/java/com/dlsc/jfxcentral2/mobile/components/LinkedObjectsBox.java @@ -0,0 +1,171 @@ +package com.dlsc.jfxcentral2.mobile.components; + +import com.dlsc.jfxcentral.data.DataRepository2; +import com.dlsc.jfxcentral.data.model.Blog; +import com.dlsc.jfxcentral.data.model.Book; +import com.dlsc.jfxcentral.data.model.Company; +import com.dlsc.jfxcentral.data.model.Learn; +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.ModelObject; +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.Video; +import com.dlsc.jfxcentral2.components.SizeSupport; +import com.dlsc.jfxcentral2.mobile.home.CategoryPreviewView; +import com.dlsc.jfxcentral2.model.Size; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.layout.VBox; + +import java.util.ArrayList; +import java.util.List; + +public class LinkedObjectsBox extends VBox { + + private final SizeSupport sizeSupport = new SizeSupport(this); + + public LinkedObjectsBox() { + getStyleClass().add("linked-objects-box"); + + updateView(); + dataProperty().addListener((obs, oldDate, newDate) -> updateView()); + } + + public LinkedObjectsBox(T data) { + this(); + setData(data); + } + + private void updateView() { + getChildren().clear(); + + T data = getData(); + if (data == null) { + return; + } + + // apps + List linkedApps = getLinkedObjects(data, RealWorldApp.class); + if (!linkedApps.isEmpty()) { + CategoryPreviewView showCasePreviewView = CategoryPreviewView.createShowCasePreviewView(linkedApps); + showCasePreviewView.sizeProperty().bind(sizeProperty()); + showCasePreviewView.setTitle("Apps"); + getChildren().add(showCasePreviewView); + } + + // libraries + List linkedLibraries = getLinkedObjects(data, Library.class); + if (!linkedLibraries.isEmpty()) { + CategoryPreviewView libraryPreviewView = CategoryPreviewView.createLibraryPreviewView(linkedLibraries); + libraryPreviewView.sizeProperty().bind(sizeProperty()); + libraryPreviewView.setTitle("Libraries"); + getChildren().add(libraryPreviewView); + } + + // books + List linkedBooks = getLinkedObjects(data, Book.class); + if (!linkedBooks.isEmpty()) { + CategoryPreviewView booksPreviewView = CategoryPreviewView.createBooksPreviewView(linkedBooks); + booksPreviewView.sizeProperty().bind(sizeProperty()); + booksPreviewView.setTitle("Books"); + getChildren().add(booksPreviewView); + } + + // videos + List