Interface Tree.Model<T>

Enclosing class:
Tree<T>

public static interface Tree.Model<T>
What the tree asks the application about its own data.

Five of the eight methods have defaults, and the three that do not are the ones only the application can answer: where the tree starts, what is under a node, and what draws it.

  • Method Summary

    Modifier and Type
    Method
    Description
    cellFor(T node)
     
    @Nullable List<T>
    children(T node)
     
    default boolean
    isLeaf(T node)
     
    default @Nullable Work<List<T>>
    load(T node)
    Fetches the children of a node that answered null to children(T).
    default float
    How wide a row's cell needs to be, in points, once the tree is deep enough to scroll sideways: the outline is made as wide as its deepest open row's indent and triangle plus this, so the cell at the deepest level gets exactly this width and every shallower cell, laid out to the same far edge, more.
    default @Nullable I18nString
    nameOf(T node)
    What to call node for an assistive technology.
    default void
    recycle(Widget<?> cell)
    The tree scrolled cell out of view; pool it for reuse if you like.
     
  • Method Details

    • roots

      List<T> roots()
      Returns:
      the top-level nodes, in the order they are shown
    • children

      @Nullable List<T> children(T node)
      Parameters:
      node - a node the tree is showing
      Returns:
      its children, or null when they are not known yet and load(T) is what fetches them. An empty list means a node with no children, which is a leaf; null is a promise, not an absence. No child may equal any other node of the tree: a node is unique by equals within a tree, and the tree refuses a duplicate as soon as both are visible.
    • isLeaf

      default boolean isLeaf(T node)
      Parameters:
      node - a node the tree is showing
      Returns:
      whether it can never have children, so no triangle is drawn. The default reads children(T): a node whose children are known and empty is a leaf, and one whose children are not known yet is not — a directory nobody has read is not a file. A model that answers false for a node with no children, an empty folder, gets a branch that opens onto the tree's "Empty" line.
    • load

      default @Nullable Work<List<T>> load(T node)
      Fetches the children of a node that answered null to children(T).

      Called at most once per node per expansion, and once more after each Tree.refresh() while the row is open, on the UI thread; the job it returns is cancelled if the row is collapsed, the tree refreshed, or the tree taken out of its scene before it lands — a tree merely moved between containers loads its open rows again when it arrives, which is the price of never leaving a row busy over a job that was dropped. The tree keeps what arrives for as long as the row is open and lets it go when the row closes, so a second expansion of the same node loads again: a model that wants it to cost nothing keeps what it loaded and answers it from children(T). A load that finds no children leaves the row an open branch with an "Empty" line under it, where the "Loading…" line stood; a load that fails closes the row.

      Parameters:
      node - the node being opened
      Returns:
      the job, or null when this model has nothing to load
    • cellFor

      Widget<?> cellFor(T node)
      Parameters:
      node - a node the tree is showing
      Returns:
      the widget that draws it, populated and ready. May be an instance kept from recycle(limn.scene.Widget<?>).
    • recycle

      default void recycle(Widget<?> cell)
      The tree scrolled cell out of view; pool it for reuse if you like.
    • nameOf

      default @Nullable I18nString nameOf(T node)
      What to call node for an assistive technology. A name from here wins: it is published over whatever the cell widget says of itself, and over the name the tree would otherwise read off the cell's labels. Answer null to let the cell name its row.

      Hand back a string this model holds. The tree compares a name by reference to decide whether it has to be resolved again, so a string built inside this call costs one allocation and one resolution per realized row per walk — which is the zero-allocation promise of a quiet frame broken for that application, though never a republish: the walk compares the resolved text, and a name that reads the same publishes nothing and raises no event. A field or an entry in the application's own data is what belongs here. The rule and the reason are ListView.Adapter#rowName's.

      Returns:
      the name, or null when the model has none to give
    • maxCellWidth

      default float maxCellWidth()
      How wide a row's cell needs to be, in points, once the tree is deep enough to scroll sideways: the outline is made as wide as its deepest open row's indent and triangle plus this, so the cell at the deepest level gets exactly this width and every shallower cell, laid out to the same far edge, more. Where the box is wider than that, the outline is the box and nothing scrolls sideways.

      A cap, not a demand: no cell is promised more than the box gives a root row past its triangle, so a width wider than the box never makes a flat tree scroll sideways, and a deep tree's outline grows by its indent alone.

      Declare it when the model knows its cells — a name and a badge, a name and a button — because the tree cannot: a row holding an Expanded has no width of its own to measure, and measuring the realized rows would move the content, the bar and every cell as a vertical scroll mounted rows of other widths. Read at every layout pass, so a constant or a field, not a computation. The number is in points at every control size; a model that follows the size step derives it from the tree's tokens.

      Returns:
      the width, or zero (the default) to let the tree choose, which is the menu's minimum width capped by the viewport: the narrowest strip this toolkit reads a row of text in. A negative or non-finite answer is taken as zero.