Class VFXTableHelper.FixedTableHelper<T>

java.lang.Object
io.github.palexdev.virtualizedfx.table.VFXTableHelper.AbstractHelper<T>
io.github.palexdev.virtualizedfx.table.VFXTableHelper.FixedTableHelper<T>
All Implemented Interfaces:
VFXTableHelper<T>
Enclosing interface:
VFXTableHelper<T>

public static class VFXTableHelper.FixedTableHelper<T> extends VFXTableHelper.AbstractHelper<T>
Concrete implementation of VFXTableHelper.AbstractHelper for ColumnsLayoutMode.FIXED. Here the range of rows and columns to display, as well as the viewport position, the virtual max x and y properties are defined as follows:

- the columns range is given by the firstColumn() element minus the buffer size VFXTable.columnsBufferSizeProperty(), (cannot be negative) and the sum between this start index and the total number of needed columns given by totalColumns(). It may happen that the number of indexes given by the range end - start + 1 is lesser than the total number of columns we need. In such cases, the range start is corrected to be end - needed + 1. A typical situation for this is when the table's horizontal position reaches the max scroll. If the table's width is 0 or the number of needed columns is 0, then the range will be Utils.INVALID_RANGE. The computation has the following dependencies: the columns' list, the table width, the horizontal position, the columns buffer size and the columns' size.

- the rows range is given by the VFXTableHelper.AbstractHelper.firstRow() element minus the buffer size VFXTable.rowsBufferSizeProperty(), (cannot be negative) and the sum between this start index and the total number of needed rows given by VFXTableHelper.AbstractHelper.totalRows(). It may happen that the number of indexes given by the range end - start + 1 is lesser than the number of rows we need. In such cases, the range start is corrected to be end - needed + 1. A typical situation for this is when the table's vertical position reaches the max scroll. If the viewport's height is 0 or the number of needed rows is 0, then the range will be Utils.INVALID_RANGE. The computation has the following dependencies: the table's height, the column's size (because it also specifies the header height, which influences the viewport's height), the vertical position, the rows buffer size, the rows' height and the items' list size.

- the viewport's position, a computation that is at the core of virtual scrolling. The viewport, which contains the columns and the cells (even though the table's viewport is a bit more complex), is not supposed to scroll by insane numbers of pixels both for performance reasons and because it is not necessary. For both the horizontal and vertical positions, we use the same technique, just using the appropriate values according to the axis we are working on. First we get the range of rows/columns to display, then their respective sizes (rows' height, columns' width). We compute the ranges to the first visible row/column, which are given by IntegerRange.of(range.getMin(), first()), in other words we limit the 'complete' ranges to the start buffer including the first row/column after the buffer. The number of indexes in the newfound ranges (given by IntegerRange.diff()) is multiplied by the respective sizes, this way we are finding the number of pixels to the first visible row/column, pixelsToFirst. At this point, we are missing only one last piece of information: how much of the first row/column do we actually see? We call this amount visibleAmountFirst and it's given by pos % size. Finally, the viewport's position is given by this formula -(pixelsToFirst + visibleAmountFirst) (for both hPos and vPos of course). If a range is equal to Utils.INVALID_RANGE, the respective position will be 0! While it's true that the calculations are more complex and 'needy', it's important to note that this approach allows avoiding 'hacks' to correctly lay out the cells in the viewport. No need for special offsets at the top or bottom anymore. The viewport's position computation has the following dependencies: the vertical and horizontal positions, the rows' height and the columns' size.

- the virtual max x and y properties, which give the total number of pixels on the x-axis and y-axis. Virtual means that it's not the actual size of the container, rather the size it would have if it was not virtualized. The two values are given by the number of rows/columns multiplied by the respective size (rows' height, columns' width). Notes: 1) the virtualMaxX is the maximum between the aforementioned computation and the table's width (because the last column must always take all the available space). 2) the virtualMaxY is going to be 0 if there are no columns in the table. The computations have the following dependencies: the table's width, the number of columns and items, the columns' size, the rows' height.

  • Constructor Details

    • FixedTableHelper

      public FixedTableHelper(VFXTable<T> table)
  • Method Details

    • initBindings

      protected void initBindings()
      Description copied from class: VFXTableHelper.AbstractHelper
      Bindings and listeners should be initialized here, automatically called after the table instance is set.
      Overrides:
      initBindings in class VFXTableHelper.AbstractHelper<T>
    • firstColumn

      public int firstColumn()

      Given by Math.floor(hPos / columnsWidth), clamped between 0 and the number of columns - 1.
      Returns:
      the index of the first visible column
    • visibleColumns

      public int visibleColumns()

      Given by Math.ceil(tableWidth / columnsWidth). 0 if the columns' width is also 0.
      Returns:
      the number of columns visible in the viewport. Not necessarily the same as VFXTableHelper.totalColumns()
    • totalColumns

      public int totalColumns()

      Given by visibleColumns() plus double the value of VFXTable.columnsBufferSizeProperty(), cannot exceed the number of columns in the table.
      Returns:
      the total number of columns in the viewport which doesn't include only the number of visible columns but also the number of buffer columns
      See Also:
    • getColumnWidth

      public double getColumnWidth(VFXTableColumn<T,?> column)

      For the ColumnsLayoutMode.FIXED mode, all columns will have the same width specified by VFXTable.columnsSizeProperty(), except for the last one that needs to take all the available space (if any left). The last column's width is given by Math.max(fixedWidth, tableWidth - ((nColumns - 1) * fixedWidth)).
      Returns:
      the width for the given column
    • getColumnPos

      public double getColumnPos(int layoutIdx, VFXTableColumn<T,?> column)

      Given by columnsWidth * layoutIndex.
      Returns:
      the x position for the given column and its layout index in the viewport
    • layoutColumn

      public boolean layoutColumn(int layoutIdx, VFXTableColumn<T,?> column)
      Lays out the given column. The layout index is necessary to identify the position of a column among the others (comes before/after).

      Positions the column at X: getColumnPos(index, column) and Y: 0.

      Sizes the column to W: getColumnWidth(column) and H: columnsHeight

      Returns:
      always true
      See Also:
    • layoutCell

      public boolean layoutCell(int layoutIdx, VFXTableCell<T> cell)
      Lays out the given cell. The layout index is necessary to identify the position of a cell among the others (comes before/after).

      The width and x position values are the exact same used by the VFXTableHelper.AbstractHelper.lastColumn() method. So both getColumnPos(int, VFXTableColumn) and getColumnWidth(VFXTableColumn) are used to find the cell's x and w respectively. However, before doing so, we must convert the given layout index to the respective column index and then extract the column (since the aforementioned methods need the column as a parameter). The conversion is done by this simple formula: columnsRange.getMin() + layoutIdx.

      The y position will be 0 and the height will be rowsHeight.

      Returns:
      always true
      See Also:
    • autosizeColumn

      public void autosizeColumn(VFXTableColumn<T,?> column)
      This method is a no-op as the operation is not possible in ColumnsLayoutMode.FIXED.
    • autosizeColumns

      public void autosizeColumns()
      In ColumnsLayoutMode.FIXED this can be still used by setting the VFXTable.columnsSizeProperty() rather than the width of each column.

      If the current state is VFXTableState.INVALID then exits immediately.

      If the last column in range (VFXTableHelper.columnsRange()), has its skin still null, then we assume that every other column is in the same situation. In such case, we need to 'delay' the operation and wait for the skin to be created, so that we can compute the columns' width.

      The first pass is to get the widest column by iterating over them, computing the width with VFXTableColumn.computePrefWidth(double) and keeping the maximum value found.

      If the state is empty (no rows), the computation ends and the VFXTable.columnsSizeProperty() is set to: Math.max(fixedW, foundMax + extra), where 'fixedW' is the current width specified by the property itself.

      The second pass is to get the widest cell among the ones in the viewport by using VFXTableRow.getWidthOf(VFXTableColumn, boolean). The forceLayout flag is true if this operation was 'delayed' before for the aforementioned reasons.

      Finally, the VFXTable.columnsSizeProperty() is set to: Math.max(Math.max(fixedW, maxColumnsW + extra), maxCellsW + extra), where 'fixedW' is the current width specified by the property itself.

      See Also:
    • visibleCells

      public int visibleCells()
      Description copied from interface: VFXTableHelper
      Depends on the implementation!
      Returns:
      the theoretical number of cells present in the viewport. It's given by visibleRows * visibleColumns, which means that it does not take into account null cells or anything else
    • isInViewport

      public boolean isInViewport(VFXTableColumn<T,?> column)

      To check whether the given column is visible this uses its index and the current state's columns range to call IntegerRange.inRangeOf(int, IntegerRange).

      The index is retrieved with VFXTable.indexOf(VFXTableColumn).

      Returns:
      whether the given column is currently visible in the viewport
    • scrollToIndex

      public void scrollToIndex(javafx.geometry.Orientation orientation, int index)
      Description copied from interface: VFXTableHelper
      Scrolls in the viewport, depending on the given direction (orientation) to:

      - the item at the given index if it's Orientation.VERTICAL

      - the column at the given index if it's Orientation.HORIZONTAL