All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.palexdev.virtualizedfx.table.paginated.PaginatedVirtualTable Maven / Gradle / Ivy

There is a newer version: 21.6.4
Show newest version
package io.github.palexdev.virtualizedfx.table.paginated;

import io.github.palexdev.mfxcore.base.properties.styleable.StyleableIntegerProperty;
import io.github.palexdev.mfxcore.utils.NumberUtils;
import io.github.palexdev.mfxcore.utils.fx.StyleUtils;
import io.github.palexdev.virtualizedfx.cell.TableCell;
import io.github.palexdev.virtualizedfx.controls.VirtualScrollPane;
import io.github.palexdev.virtualizedfx.enums.ColumnsLayoutMode;
import io.github.palexdev.virtualizedfx.table.*;
import io.github.palexdev.virtualizedfx.utils.VSPUtils;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.ObservableList;
import javafx.css.CssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleablePropertyFactory;
import javafx.scene.control.Skin;

import java.util.List;

/**
 * Extension of {@link VirtualTable} to offer pagination features.
 * 

* In addition to all the inherited features this adds: *

- The current displayed page, {@link #currentPageProperty()} *

- The max number of pages, {@link #maxPageProperty()} *

- The number of rows per page, {@link #rowsPerPageProperty()}. Note that this is also * settable via CSS *

* Note that pages start from index 1. *

* This table also has its own skin which is basically the same as {@link VirtualTable} but adapted to * resize the control depending on the {@link #rowsPerPageProperty()} *

* Little tips and warnings: *

* Note that this is a naive implementation. Some things/components, like the {@link TableState} or {@link TableRow}, have been * adapted to work with this but if you are not careful you could potentially break or mess things up. *

* For example: the correct way to scroll is to change the current page property, but nothing prevents you to set the position * using the related setters. * To be more precise you can still set the hPos freely as pages are vertically arranged. *

* This table is intended to use implementations of {@link PaginatedHelper}. Again, nothing prevents you from setting a * {@link #tableHelperSupplierProperty()} that only implements {@link TableHelper}, don't do that! In such case note that * {@link #goToPage(int)} won't work and will end with an exception. */ public class PaginatedVirtualTable extends VirtualTable { //================================================================================ // Properties //================================================================================ private final String STYLE_CLASS = "paginated-virtual-table"; private final IntegerProperty currentPage = new SimpleIntegerProperty(1) { @Override public void set(int newValue) { int clamped = NumberUtils.clamp(newValue, 1, getMaxPage()); super.set(clamped); } @Override protected void invalidated() { int page = get(); changePage(page); } }; private final ReadOnlyIntegerWrapper maxPage = new ReadOnlyIntegerWrapper() { @Override public void set(int newValue) { int clamped = Math.max(1, newValue); super.set(clamped); } @Override protected void invalidated() { int max = get(); int curr = NumberUtils.clamp(getCurrentPage(), 1, max); setCurrentPage(curr); } }; //================================================================================ // Constructors //================================================================================ public PaginatedVirtualTable() { super(); initialize(); } public PaginatedVirtualTable(ObservableList items, TableColumn>... columns) { super(items, columns); initialize(); } public PaginatedVirtualTable(ObservableList items, ObservableList>> tableColumns) { super(items, tableColumns); initialize(); } //================================================================================ // Methods //================================================================================ private void initialize() { getStyleClass().add(STYLE_CLASS); setTableHelperSupplier(() -> { ColumnsLayoutMode mode = getColumnsLayoutMode(); return (mode == ColumnsLayoutMode.FIXED) ? new PaginatedHelper.FixedPaginatedTableHelper(this) : new PaginatedHelper.VariablePaginatedTableHelper(this); }); } /** * Shortcut for {@link #setRowsPerPage(int)}. * When the {@link #currentPageProperty()} is invalidated {@link #changePage(int)} is automatically called */ public void goToPage(int page) { setCurrentPage(page); } /** * Shortcut for {@link #goToPage(int)} with 1 as parameter. */ public void goToFirstPage() { goToPage(1); } /** * Shortcut for {@link #goToPage(int)} with {@link #getMaxPage()} as parameter. */ public void goToLastPage() { goToPage(getMaxPage()); } /** * Responsible for updating {@link #maxPageProperty()} when needed. *

* The value is given by {@code Math.ceil(rows / rowsPerPage)}. */ public void updateMaxPage() { int rows = getItems().size(); int rpp = getRowsPerPage(); int max = (int) Math.ceil(rows / (double) rpp); setMaxPage(max); } /** * Gets the current {@link PaginatedHelper} and calls {@link PaginatedHelper#goToPage(int)}, but * before doing so it ensures that the max page is correct by calling {@link #updateMaxPage()}. */ protected void changePage(int page) { TableHelper helper = getTableHelper(); if (!(helper instanceof PaginatedHelper)) throw new IllegalStateException("The table's helper is not of type PaginatedHelper!"); updateMaxPage(); PaginatedHelper pHelper = (PaginatedHelper) helper; pHelper.goToPage(page); } //================================================================================ // Overridden Methods //================================================================================ /** * The paginated table cannot scroll to a desired row. * * @throws UnsupportedOperationException */ @Override public void scrollToFirstRow() { throw new UnsupportedOperationException("The paginated table cannot scroll to a desired row"); } /** * The paginated table cannot scroll to a desired row. * * @throws UnsupportedOperationException */ @Override public void scrollToLastRow() { throw new UnsupportedOperationException("The paginated table cannot scroll to a desired row"); } @Override protected void onCellHeightChanged() { TableHelper helper = getTableHelper(); if (helper != null) { helper.computeEstimatedSize(); } if (getWidth() != 0.0 && getHeight() != 0.0) { // TODO test with w and h = 0 initially if (!getViewportManager().init()) { requestViewportLayout(); } else { goToPage(1); scrollToColumn(0); } } } @Override protected Skin createDefaultSkin() { return new PaginatedVirtualTableSkin<>(this); } @Override protected List> getControlCssMetaData() { return getClassCssMetaData(); } @Override public VirtualScrollPane wrap() { return VSPUtils.wrap(this); } //================================================================================ // Styleable Properties //================================================================================ private final StyleableIntegerProperty rowsPerPage = new StyleableIntegerProperty( StyleableProperties.ROWS_PER_PAGE, this, "rowsPerPage", 5 ) { @Override protected void invalidated() { updateMaxPage(); changePage(getCurrentPage()); requestViewportLayout(); } }; public int getRowsPerPage() { return rowsPerPage.get(); } /** * Specifies the number of rows to display per page. *

* Note that this, combined with {@link #cellHeightProperty()}, determines the height of the virtual table. *

* This is settable via CSS with the "-fx-rows-per-page" property. */ public StyleableIntegerProperty rowsPerPageProperty() { return rowsPerPage; } public void setRowsPerPage(int rowsPerPage) { this.rowsPerPage.set(rowsPerPage); } //================================================================================ // CssMetaData //================================================================================ private static class StyleableProperties { private static final StyleablePropertyFactory> FACTORY = new StyleablePropertyFactory<>(VirtualTable.getClassCssMetaData()); private static final List> cssMetaDataList; private static final CssMetaData, Number> ROWS_PER_PAGE = FACTORY.createSizeCssMetaData( "-fx-rows-per-page", PaginatedVirtualTable::rowsPerPageProperty, 5 ); static { cssMetaDataList = StyleUtils.cssMetaDataList( VirtualTable.getClassCssMetaData(), ROWS_PER_PAGE ); } } public static List> getClassCssMetaData() { return StyleableProperties.cssMetaDataList; } //================================================================================ // Getters/Setters //================================================================================ public int getCurrentPage() { return currentPage.get(); } /** * Specifies the current displayed page. */ public IntegerProperty currentPageProperty() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage.set(currentPage); } public int getMaxPage() { return maxPage.get(); } /** * Specifies the maximum number of pages, aka last page number. */ public ReadOnlyIntegerProperty maxPageProperty() { return maxPage.getReadOnlyProperty(); } protected void setMaxPage(int maxPage) { this.maxPage.set(maxPage); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy