Skip to content

Commit

Permalink
Add pagination components and enhance header text display, update styles
Browse files Browse the repository at this point in the history
1. Add LotwPagination component.
2. Add LearnPagination component.
3. Wrap Details Page header text for better display.
4. Fix sorting error on Learn category page.
5. Remove "Related" text from header.
6. Add pressed styles for back button, more button, and others.
7. Update css
  • Loading branch information
leewyatt committed Jul 24, 2024
1 parent a185843 commit cfc8886
Show file tree
Hide file tree
Showing 12 changed files with 387 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,17 @@
import com.dlsc.jfxcentral2.utils.MobileLinkUtil;
import com.dlsc.jfxcentral2.utils.ModelObjectTool;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.materialdesign.MaterialDesign;

import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class LearnPagination<T extends Learn> extends VBox {
public class LearnPagination<T extends Learn> extends MobilePagination<T> {

private static final String DEFAULT_STYLE_CLASS = "learn-pagination";
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
Expand All @@ -42,11 +33,6 @@ public class LearnPagination<T extends Learn> extends VBox {
public LearnPagination() {
getStyleClass().add(DEFAULT_STYLE_CLASS);

// Label title = new Label();
// title.getStyleClass().add("title");
// title.setWrapText(true);
// title.textProperty().bind(itemProperty().map(item -> item == null ? "" : item.getName()));

Label dateLabel = new Label();
dateLabel.getStyleClass().add("date-label");
dateLabel.textProperty().bind(itemProperty().map(item -> item == null ? "" : DATE_FORMATTER.format(item.getCreatedOn())));
Expand All @@ -67,9 +53,6 @@ public LearnPagination() {
authorBox.getChildren().add(avatarView);
}));
authorBox.getChildren().addAll(spacer, dateLabel);

// scroll to top
scrollPane.setVvalue(0);
});

CustomMarkdownView markdownView = new CustomMarkdownView();
Expand All @@ -90,90 +73,16 @@ public LearnPagination() {
return "";
}, itemProperty(), baseURLProperty()));

Button previousButton = new Button();
previousButton.getStyleClass().addAll("nav-button", "previous-button");
previousButton.setGraphic(new FontIcon(MaterialDesign.MDI_CHEVRON_LEFT));
previousButton.disableProperty().bind(index.isEqualTo(0));
previousButton.setOnAction(e -> setIndex(getIndex() - 1));

Button nextButton = new Button();
nextButton.getStyleClass().addAll("nav-button", "next-button");
nextButton.setGraphic(new FontIcon(MaterialDesign.MDI_CHEVRON_RIGHT));
nextButton.disableProperty().bind(Bindings.createBooleanBinding(() -> getIndex() >= items.size() - 1, indexProperty(), getItems()));
nextButton.setOnAction(e -> setIndex(getIndex() + 1));

Label pageLabel = new Label();
pageLabel.getStyleClass().add("page-label");
pageLabel.textProperty().bind(Bindings.concat(indexProperty().add(1), " / ", Bindings.size(items)));

HBox navBox = new HBox(previousButton, pageLabel, nextButton);
navBox.getStyleClass().add("nav-box");
pageLabel.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(pageLabel, Priority.ALWAYS);

VBox contentBox = new VBox(authorBox, markdownView);
contentBox.getStyleClass().add("content-box");

scrollPane.setContent(contentBox);
scrollPane.getStyleClass().add("mobile");
scrollPane.setMaxHeight(Double.MAX_VALUE);
VBox.setVgrow(scrollPane, Priority.ALWAYS);

getChildren().addAll(scrollPane, navBox);

itemProperty().bind(Bindings.createObjectBinding(() -> {
int currentIndex = getIndex();
int size = getItems().size();
if (currentIndex < 0 || currentIndex >= size) {
return null;
}

return getItems().get(currentIndex);
}, indexProperty(), getItems()));
}

public final void setSelectedItem(T item) {
setIndex(getItems().indexOf(item));
}

// learn items

private final ObservableList<T> items = FXCollections.observableArrayList();

public ObservableList<T> getItems() {
return items;
}

// index

private final IntegerProperty index = new SimpleIntegerProperty(this, "index", -1);

public final IntegerProperty indexProperty() {
return index;
}

public final int getIndex() {
return index.get();
}

public final void setIndex(int index) {
this.index.set(index);
}

// item

private final ReadOnlyObjectWrapper<T> item = new ReadOnlyObjectWrapper<>(this, "item");

public final T getItem() {
return item.get();
}

public final ReadOnlyObjectWrapper<T> itemProperty() {
return item;
}

private void setItem(T item) {
this.item.set(item);
setCellFactory(index -> {
scrollPane.setVvalue(0);
return scrollPane;
});
}

// base url
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.dlsc.jfxcentral2.mobile.components;

import com.dlsc.jfxcentral.data.DataRepository2;
import com.dlsc.jfxcentral.data.model.LinksOfTheWeek;
import com.dlsc.jfxcentral2.components.CustomMarkdownView;
import com.dlsc.jfxcentral2.components.PrettyScrollPane;
import javafx.beans.binding.Bindings;

public class LotwPagination extends MobilePagination<LinksOfTheWeek> {

private static final String DEFAULT_STYLE_CLASS = "lotw-pagination";
private final PrettyScrollPane scrollPane = new PrettyScrollPane();

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

CustomMarkdownView markdownView = new CustomMarkdownView();
markdownView.mdStringProperty().bind(Bindings.createStringBinding(() -> {
LinksOfTheWeek lotw = getItem();
if (lotw == null) {
return "";
}
return DataRepository2.getInstance().getLinksOfTheWeekReadMe(lotw);
}, itemProperty()));

scrollPane.setContent(markdownView);
scrollPane.getStyleClass().add("mobile");

setCellFactory(index -> {
scrollPane.setVvalue(0);
return scrollPane;
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.dlsc.jfxcentral2.model.Size;
import com.dlsc.jfxcentral2.utils.MobileLinkUtil;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.Button;
Expand All @@ -21,6 +22,7 @@ public class MobilePageHeader extends StackPane {

private static final String DEFAULT_STYLE_CLASS = "mobile-page-header";
private final SizeSupport sizeSupport = new SizeSupport(this);
private final Label categoryTitle;

public MobilePageHeader() {
getStyleClass().add(DEFAULT_STYLE_CLASS);
Expand All @@ -33,8 +35,13 @@ public MobilePageHeader() {
HBox topBox = new HBox(backButton);
topBox.getStyleClass().add("top-box");

Label categoryTitle = new Label();
categoryTitle = new Label();
categoryTitle.getStyleClass().add("title");
categoryTitle.setWrapText(true);
categoryTitle.setMinHeight(-1);
categoryTitle.setMaxHeight(Double.MAX_VALUE);

// categoryTitle.
categoryTitle.textProperty().bind(titleProperty());
categoryTitle.graphicProperty().bind(Bindings.createObjectBinding(() -> {
Ikon icon = getIcon();
Expand All @@ -47,10 +54,29 @@ public MobilePageHeader() {
return null;
}, iconProperty(), previewImageProperty()));

BooleanBinding longTitleProperty = Bindings.createBooleanBinding(() -> {
String title = getTitle();
boolean isShortTitle = title == null || title.split(" ").length < 7 || title.length() < 38;
return getIcon() == null && getPreviewImage() == null && !isShortTitle;
}, widthProperty(), iconProperty(), previewImageProperty(), titleProperty());

updateLongTitle(longTitleProperty.get());
longTitleProperty.addListener((obs, oldVal, newVal) -> updateLongTitle(newVal));

getChildren().addAll(categoryTitle, topBox);
setMaxHeight(Region.USE_PREF_SIZE);
}

private void updateLongTitle(boolean isLongTitle) {
if (isLongTitle) {
if (!categoryTitle.getStyleClass().contains("long-title")) {
categoryTitle.getStyleClass().add("long-title");
}
} else {
getStyleClass().remove("long-title");
}
}

// size support

public final ObjectProperty<Size> sizeProperty() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.dlsc.jfxcentral2.mobile.components;

import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.materialdesign.MaterialDesign;

public class MobilePagination<T> extends VBox {

private static final String DEFAULT_STYLE_CLASS = "mobile-pagination";
private final StackPane contentWrapper;

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

Button previousButton = new Button();
previousButton.getStyleClass().addAll("nav-button", "previous-button");
previousButton.setGraphic(new FontIcon(MaterialDesign.MDI_CHEVRON_LEFT));
previousButton.disableProperty().bind(index.isEqualTo(0));
previousButton.setOnAction(e -> setIndex(getIndex() - 1));

Button nextButton = new Button();
nextButton.getStyleClass().addAll("nav-button", "next-button");
nextButton.setGraphic(new FontIcon(MaterialDesign.MDI_CHEVRON_RIGHT));
nextButton.disableProperty().bind(Bindings.createBooleanBinding(() -> getIndex() >= items.size() - 1, indexProperty(), getItems()));
nextButton.setOnAction(e -> setIndex(getIndex() + 1));

Label pageLabel = new Label();
pageLabel.getStyleClass().add("page-label");
pageLabel.textProperty().bind(Bindings.concat(indexProperty().add(1), " / ", Bindings.size(items)));

HBox navBox = new HBox(previousButton, pageLabel, nextButton);
navBox.getStyleClass().add("nav-box");
pageLabel.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(pageLabel, Priority.ALWAYS);

contentWrapper = new StackPane();
contentWrapper.getStyleClass().add("content-wrapper");
VBox.setVgrow(contentWrapper, Priority.ALWAYS);

getChildren().addAll(contentWrapper, navBox);

itemProperty().bind(Bindings.createObjectBinding(() -> {
boolean validatedIndex = isValidIndex();
return validatedIndex ? getItems().get(getIndex()) : null;
}, indexProperty(), getItems()));

updatedPageView();
indexProperty().addListener(it -> updatedPageView());
}

protected void updatedPageView() {
boolean validatedIndex = isValidIndex();
if (validatedIndex) {
contentWrapper.getChildren().setAll(getCellFactory().call(getIndex()));
} else {
contentWrapper.getChildren().clear();
}
}

private boolean isValidIndex() {
int currentIndex = getIndex();
int size = getItems().size();
return currentIndex >= 0 && currentIndex < size;
}

public final void setSelectedItem(T item) {
setIndex(getItems().indexOf(item));
}

// items

private final ObservableList<T> items = FXCollections.observableArrayList();

public ObservableList<T> getItems() {
return items;
}

// index

private final IntegerProperty index = new SimpleIntegerProperty(this, "index", -1);

public final IntegerProperty indexProperty() {
return index;
}

public final int getIndex() {
return index.get();
}

public final void setIndex(int index) {
this.index.set(index);
}

// item

private final ReadOnlyObjectWrapper<T> item = new ReadOnlyObjectWrapper<>(this, "item");

public final T getItem() {
return item.get();
}

public final ReadOnlyObjectWrapper<T> itemProperty() {
return item;
}

private void setItem(T item) {
this.item.set(item);
}

// cellFactory

private final ObjectProperty<Callback<Integer, Node>> cellFactory = new SimpleObjectProperty<>(this, "cellFactory", i -> new Label("Page " + (i + 1)));

public final ObjectProperty<Callback<Integer, Node>> cellFactoryProperty() {
return cellFactory;
}

public final Callback<Integer, Node> getCellFactory() {
return cellFactory.get();
}

public final void setCellFactory(Callback<Integer, Node> cellFactory) {
cellFactoryProperty().set(cellFactory);
}

}
Loading

0 comments on commit cfc8886

Please sign in to comment.