Class TableHelper.VariableTableHelper

All Implemented Interfaces:
TableHelper
Direct Known Subclasses:
PaginatedHelper.VariablePaginatedTableHelper
Enclosing interface:
TableHelper

public static class TableHelper.VariableTableHelper extends TableHelper.FixedTableHelper
Extension of TableHelper.FixedTableHelper made to work specifically with ColumnsLayoutMode.VARIABLE.

Many of the methods of the other mode can be reused for this, just a few need their behavior to be redefined.

As you can guess, this is not the most efficient. All columns are laid out in the viewport which directly translates to "there are more cells in the viewport". You can also consider this mode as "partially virtualized", rows will still be virtualized but since columns widths are variable we have no way to easily and consistently virtualize them too.

The advantage of this mode is of course having columns that can be resized programmatically or by a gesture at runtime.

  • Constructor Details

    • VariableTableHelper

      public VariableTableHelper(VirtualTable<?> table)
  • Method Details

    • firstColumn

      public int firstColumn()
      Specified by:
      firstColumn in interface TableHelper
      Overrides:
      firstColumn in class TableHelper.FixedTableHelper
      Returns:
      0 or -1 if the columns list is empty
    • lastColumn

      public int lastColumn()
      Specified by:
      lastColumn in interface TableHelper
      Overrides:
      lastColumn in class TableHelper.FixedTableHelper
      Returns:
      the columns list size -1
    • maxColumns

      public int maxColumns()
      Specified by:
      maxColumns in interface TableHelper
      Overrides:
      maxColumns in class TableHelper.FixedTableHelper
      Returns:
      the size of the columns list
    • columnsRange

      public io.github.palexdev.mfxcore.base.beans.range.IntegerRange columnsRange()
      Description copied from class: TableHelper.FixedTableHelper

      Note that the result given by TableHelper.FixedTableHelper.maxColumns() to compute the index of the first column, is clamped so that it will never be greater then the number of columns in the table.

      Will return a range of (-1, -1) if the table has no columns.
      Specified by:
      columnsRange in interface TableHelper
      Overrides:
      columnsRange in class TableHelper.FixedTableHelper
      Returns:
      an IntegerRange made from the values of firstColumn() and lastColumn(). Will return a range of (-1, -1) if the table has no columns
    • xPosBinding

      public DoubleBinding xPosBinding()
      This binding holds the horizontal position of the viewport. This is the direction along the estimated breath.

      This is not virtualized as columns have variable widths and the value is simply given by -table.getHPos().

      Specified by:
      xPosBinding in interface TableHelper
      Overrides:
      xPosBinding in class TableHelper.FixedTableHelper
    • scrollToColumn

      public void scrollToColumn(int index)
      Scrolls the viewport to the given column index.

      This is actually more complicated for this layout mode as we can't always get the position at which a column will be in the viewport. In fact, if the table has not been laid out yet, meaning that its skin is null, or if the interested column has not been laid out yet there's no way to know where it is in the viewport.

      For this reason this distinguish between two cases:

      1) Everything has been laid out at least once: the column position is given by column.getRegion().getBoundsInParent().getMinX()

      2) We cannot rely on the aforementioned method, we resort on the "super" method. Since VirtualTable specifies the minimum width every column must have at the initialization we can easily predict were it will be at the start.

      Specified by:
      scrollToColumn in interface TableHelper
      Overrides:
      scrollToColumn in class TableHelper.FixedTableHelper
    • autosizeColumn

      public void autosizeColumn(TableColumn<?,? extends TableCell<?>> column)
      Attempts at auto-sizing the given column to fit its content.

      To accomplish this we need the current state of the table, VirtualTable.stateProperty(), and the index of the given column, VirtualTable.getColumnIndex(TableColumn). (if the state is completely empty, TableState.isEmptyAll(), exits immediately).

      We get the rows from the state and then use TableRow.getWidthOf(int) to get the preferred width of the cell at index (same index of column). From these results we get the maximum value and this will be the new width of the column.

      The last column is handled differently though. First we compute the total width of all the columns before. If this is lesser than the table width than the column will be resized to make it occupy all the available space. If this is not the case, then we fall back to the normal handling.
      Specified by:
      autosizeColumn in interface TableHelper
      Overrides:
      autosizeColumn in class TableHelper.FixedTableHelper
    • autosizeColumns

      public void autosizeColumns()
      Calls autosizeColumn(TableColumn) on all the columns in the table.
      Specified by:
      autosizeColumns in interface TableHelper
      Overrides:
      autosizeColumns in class TableHelper.FixedTableHelper
    • computePositions

      public Map<Orientation,List<Double>> computePositions(TableState<?> state, boolean forceXComputation, boolean forceYComputation)
      Given a certain state, computes the positions of each column/row/cell as a map. The key is an Orientation value to differentiate between the vertical and horizontal positions.

      Most of the time this computation is not needed and the old positions can be reused, but if for whatever reason the computation is believed to be necessary then it's possible to force it by setting the desired parameter flags as true.

      X Positions Computation

      The horizontal positions are computed by iterating over all the columns and getting their width as the maximum between its current width and the minimum width specified by VirtualTable.columnSizeProperty(). The positions are actually computed with a simple accumulator.

      Horizontal positions are not computed unless at least one of these conditions is true:

      - forceXComputation flag is true

      - the positions have not been computed before

      Y Positions Computation

      The vertical positions are computed by using a DoubleStream.iterate(double, DoubleUnaryOperator) with rowsNum * cellHeight as the seed and x -> x - cellHeight as the operator. The stream is also limited, DoubleStream.limit(long), to the number of rows we need, the results are stored in a list and put in the positions map with Orientation.VERTICAL as the key.

      Vertical positions are not computed unless at least one of these conditions is true:

      - forceYComputation flag is true

      - the positions have not been computed before

      - the number of positions previously computed is not equal to the number of rows we need

      Specified by:
      computePositions in interface TableHelper
      Overrides:
      computePositions in class TableHelper.FixedTableHelper
      Parameters:
      forceXComputation - forces the computation of the HORIZONTAL positions even if not needed
      forceYComputation - forces the computation of the VERTICAL positions even if not needed
    • layout

      public void layout()
      Entirely responsible for laying out columns/rows/cells.

      The layout makes use of the current table' state, VirtualTable.stateProperty(), and the positions computed by computePositions(TableState, boolean, boolean), this is invoked without forcing the re-computation.

      Exits immediately if the state is completely empty, TableState.isEmptyAll(), if TableHelper.AbstractHelper.invalidatedPos() returns true, or if VirtualTable.needsViewportLayoutProperty() is false.

      Before proceeding with layout retrieves the following parameters:

      - the columns height

      - the columns range

      - the X positions

      - the cells height

      - the Y positions

      - the Y offset with TableHelper.AbstractHelper.verticalOffset()

      Columns are laid out from left to right, relocated at the extracted X position and at Y 0; and resized to the previously gathered height. The width is computed by LayoutUtils.boundWidth(Node) to honor the min, pref, and max values. The last column is an exception because if not all the space of the table was occupied by laying out the previous columns than its width will be set to the entire remaining space.

      Rows are laid out from top to bottom, relocated at X 0 and at the extracted Y position (+ the Y offset); and resized with the previously gathered height. The width is given by the current VirtualTable.estimatedSizeProperty() so that rows always have the same width of the column's container.

      For each row in the loop it also lays out their cells. Each cell is relocated at the extracted X position and at Y 0; and resized to the previously gathered cell height. The width is the same of the corresponding column.

      Note that the rows layout process won't even start if the current state is half-empty, TableState.empty().
      Specified by:
      layout in interface TableHelper
      Overrides:
      layout in class TableHelper.FixedTableHelper