Skip to content

Commit

Permalink
✨ Implement layout hooks for cells
Browse files Browse the repository at this point in the history
♻️ Refactor layout methods in helpers to accept Cell objects rather than Nodes

Signed-off-by: palexdev <alessandro.parisi406@gmail.com>
  • Loading branch information
palexdev committed May 21, 2024
1 parent c40837a commit fd18afd
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 21 deletions.
10 changes: 9 additions & 1 deletion src/main/java/io/github/palexdev/virtualizedfx/cells/Cell.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,15 @@ public interface Cell<T> {
*/
void updateItem(T item);

// TODO implement layout hooks
/**
* The system automatically calls this before the cell is laid out.
*/
default void beforeLayout() {}

/**
* The system automatically calls this after the cell is laid out.
*/
default void afterLayout() {}

/**
* Virtualized containers that make use of a cache to store unneeded cells that may be required again in a second time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,13 @@ default Position getViewportPosition() {
}

/**
* Lays out the given node.
* Lays out the given cell.
* The row and column layout indexes are necessary to identify the position of a cell among the others
* (comes before/after, above/below).
*
* @see VFXGridSkin#layout()
*/
void layout(int rowLayoutIndex, int columnLayoutIndex, Node node);
void layout(int rowLayoutIndex, int columnLayoutIndex, Cell<T> cell);

/**
* @return the total size of each cell, given by the {@link VFXGrid#cellSizeProperty()} summed to the horizontal and
Expand Down Expand Up @@ -599,12 +599,15 @@ public ReadOnlyObjectProperty<Position> viewportPositionProperty() {
* {@code totalCellHeight * rowIndex}, the width and height are given by the {@link VFXGrid#cellSizeProperty()}.
*/
@Override
public void layout(int rowLayoutIndex, int columnLayoutIndex, Node node) {
public void layout(int rowLayoutIndex, int columnLayoutIndex, Cell<T> cell) {
Node node = cell.toNode();
double x = getTotalCellSize().getWidth() * columnLayoutIndex;
double y = getTotalCellSize().getHeight() * rowLayoutIndex;
double w = grid.getCellSize().getWidth();
double h = grid.getCellSize().getHeight();
cell.beforeLayout();
node.resizeRelocate(x, y, w, h);
cell.afterLayout();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import io.github.palexdev.virtualizedfx.cells.Cell;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
Expand Down Expand Up @@ -172,7 +171,7 @@ protected void addListeners() {
* managed for the {@link VFXGrid}. In other words, it doesn't matter whether our range is [1, 5] or [4, 6] or whatever,
* the layout index will always start from 0 and increment towards the end of the range.
* <p>
* The layout is performed by {@link VFXGridHelper#layout(int, int, Node)}, the two aforementioned counters are passed
* The layout is performed by {@link VFXGridHelper#layout(int, int, Cell)}, the two aforementioned counters are passed
* as arguments.
* <p></p>
* <pre>
Expand Down Expand Up @@ -202,7 +201,7 @@ protected void layout() {
for (Integer cIdx : state.getColumnsRange()) {
int linear = GridUtils.subToInd(nColumns, rIdx, cIdx);
if (linear >= grid.size()) break outer_loop;
helper.layout(i, j, cells.get(linear).toNode());
helper.layout(i, j, cells.get(linear));
j++;
}
i++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,12 @@ default Position getViewportPosition() {
double computeSize(Node node);

/**
* Lays out the given node. The index parameter is necessary to identify the position of a cell compared to the others
* Lays out the given cell. The index parameter is necessary to identify the position of a cell compared to the others
* (comes before or after).
*
* @param absIndex the absolute index of the given node/cell, see {@link VFXListSkin#layout()}
* @param layoutIndex the absolute index of the given node/cell, see {@link VFXListSkin#layout()}
*/
void layout(int absIndex, Node node);
void layout(int layoutIndex, Cell<T> cell);


/**
Expand Down Expand Up @@ -424,11 +424,14 @@ public double computeSize(Node node) {
* computed by {@link #computeSize(Node)}, and the height is given by the {@link VFXList#cellSizeProperty()}.
*/
@Override
public void layout(int absIndex, Node node) {
double y = getTotalCellSize() * absIndex;
public void layout(int layoutIndex, Cell<T> cell) {
Node node = cell.toNode();
double y = getTotalCellSize() * layoutIndex;
double w = computeSize(node);
double h = list.getCellSize();
cell.beforeLayout();
node.resizeRelocate(0, y, w, h);
cell.afterLayout();
}

@Override
Expand Down Expand Up @@ -611,11 +614,14 @@ public double computeSize(Node node) {
* computed by {@link #computeSize(Node)}, and the width is given by the {@link VFXList#cellSizeProperty()}.
*/
@Override
public void layout(int absIndex, Node node) {
double x = getTotalCellSize() * absIndex;
public void layout(int layoutIndex, Cell<T> cell) {
Node node = cell.toNode();
double x = getTotalCellSize() * layoutIndex;
double w = list.getCellSize();
double h = computeSize(node);
cell.beforeLayout();
node.resizeRelocate(x, 0, w, h);
cell.afterLayout();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import io.github.palexdev.virtualizedfx.cells.Cell;
import javafx.beans.InvalidationListener;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;

Expand Down Expand Up @@ -166,7 +165,7 @@ protected void addListeners() {
* The loop on the cells uses an external {@code i} variable that tracks the iteration count. This is because cells in the
* state are already ordered by their index (since the state uses a {@link TreeMap}), and the layout is 'absolute'.
* Meaning that the index of the cell is irrelevant for its position, we just care about which comes before/after.
* The layout is performed by {@link VFXListHelper#layout(int, Node)}, the index given to that method is the
* The layout is performed by {@link VFXListHelper#layout(int, Cell)}, the index given to that method is the
* {@code i} variable.
* <p></p>
* <pre>
Expand All @@ -190,7 +189,7 @@ protected void layout() {
if (state != VFXListState.EMPTY) {
int i = 0;
for (C cell : state.getCellsByIndex().values()) {
helper.layout(i, cell.toNode());
helper.layout(i, cell);
i++;
}
onLayoutCompleted(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.github.palexdev.mfxcore.observables.OnInvalidated;
import io.github.palexdev.mfxcore.observables.When;
import io.github.palexdev.mfxcore.utils.NumberUtils;
import io.github.palexdev.virtualizedfx.cells.Cell;
import io.github.palexdev.virtualizedfx.cells.TableCell;
import io.github.palexdev.virtualizedfx.enums.ColumnsLayoutMode;
import io.github.palexdev.virtualizedfx.utils.Utils;
Expand Down Expand Up @@ -192,16 +193,18 @@ default void layoutRow(int layoutIdx, VFXTableRow<T> row) {
double w = getVirtualMaxX();
double h = getTable().getRowsHeight();
double y = layoutIdx * h;
row.beforeLayout();
row.resizeRelocate(0, y, w, h);
row.afterLayout();
}

/**
* Lays out the given node/cell.
* Lays out the given cell.
* The layout index is necessary to identify the position of a cell among the others (comes before/after).
*
* @see VFXTableRow#layoutCells()
*/
boolean layoutCell(int layoutIdx, Node node);
boolean layoutCell(int layoutIdx, TableCell<T> cell);

/**
* Determines and sets the ideal width for the given column, where 'ideal' means that
Expand Down Expand Up @@ -713,15 +716,18 @@ public boolean layoutColumn(int layoutIdx, VFXTableColumn<T, ?> column) {
* @return always true
*/
@Override
public boolean layoutCell(int layoutIdx, Node node) {
public boolean layoutCell(int layoutIdx, TableCell<T> cell) {
VFXTable<T> table = getTable();
IntegerRange columnsRange = columnsRange();
int colIndex = columnsRange.getMin() + layoutIdx;
VFXTableColumn<T, ? extends TableCell<T>> column = table.getColumns().get(colIndex);
Node node = cell.toNode();
double x = getColumnPos(layoutIdx, column);
double w = getColumnWidth(column);
double h = table.getRowsHeight();
cell.beforeLayout();
node.resizeRelocate(x, 0, w, h);
cell.afterLayout();
return true;
}

Expand Down Expand Up @@ -1152,13 +1158,20 @@ public boolean layoutColumn(int layoutIdx, VFXTableColumn<T, ?> column) {
* the corresponding column, the width, positions and visibility computations are already done when invoking
* {@link #layoutColumn(int, VFXTableColumn)}. Obviously, to do so, we first need to get the cell's corresponding
* column from {@link VFXTable#getColumns()} by the given index.
* <p></p>
* Note: the pre/post layout hooks defined by {@link Cell} are called even if the cell will only be set to
* hidden. This allows implementations to perform actions depending on the visibility state without relying on
* listeners.
*/
@Override
public boolean layoutCell(int layoutIdx, Node node) {
public boolean layoutCell(int layoutIdx, TableCell<T> cell) {
ObservableList<VFXTableColumn<T, ? extends TableCell<T>>> columns = table.getColumns();
VFXTableColumn<T, ? extends TableCell<T>> column = columns.get(layoutIdx);
Node node = cell.toNode();
cell.beforeLayout();
if (!isInViewport(column)) {
node.setVisible(false);
cell.afterLayout();
return false;
}
double w = getColumnWidth(column);
Expand All @@ -1167,6 +1180,7 @@ public boolean layoutCell(int layoutIdx, Node node) {
if (node.isVisible() && node.getLayoutX() == x && node.getLayoutBounds().getWidth() == w) return false;
node.resizeRelocate(x, 0, w, h);
node.setVisible(true);
cell.afterLayout();
return true;
}

Expand Down

0 comments on commit fd18afd

Please sign in to comment.