//
// Copyright (c) 2008, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 20 Jul 08 Brian Frank Creation
//
using gfx
**
** Tree displays a hierarchy of tree nodes which can be
** expanded and collapsed.
**
@Serializable
class Tree : Widget
{
**
** Default constructor.
**
new make(|This|? f := null)
{
if (f != null) f(this)
}
**
** Callback when node is double clicked or Return/Enter
** key is pressed.
**
** Event id fired:
** - `EventId.modified`
**
** Event fields:
** - `Event.data`: the `TreeModel` node object
**
once EventListeners onAction() { EventListeners() }
**
** Callback when selected nodes change.
**
** Event id fired:
** - `EventId.select`
**
** Event fields:
** - `Event.data`: the primary selection node object.
**
once EventListeners onSelect() { EventListeners() }
**
** Callback when user invokes a right click popup action.
** If the callback wishes to display a popup, then set
** the `Event.popup` field with menu to open. If multiple
** callbacks are installed, the first one to return a nonnull
** popup consumes the event.
**
** Event id fired:
** - `EventId.popup`
**
** Event fields:
** - `Event.data`: the primary selection node object, or
** 'null' if this is a background popup.
** - `Event.pos`: the mouse position of the popup.
**
once EventListeners onPopup() { EventListeners() }
**
** Horizontal scroll bar.
**
@Transient ScrollBar hbar := ScrollBar.makeNative(Orientation.horizontal) { private set }
**
** Vertical scroll bar.
**
@Transient ScrollBar vbar := ScrollBar.makeNative(Orientation.vertical) { private set }
**
** Background color of tree, or null for platform default.
**
const Color? bg := null
**
** Draw a border around the widget. Default is true. This
** field cannot be changed once the widget is constructed.
**
const Bool border := true
**
** True to enable multi-node selection, false for single
** node selection. Default is false. This field cannot
** be changed once the widget is constructed.
**
const Bool multi := false
**
** Backing data model of tree.
**
TreeModel model := TreeModel()
**
** Select the given item in the tree.
**
native Void select(Obj node)
**
** Get and set the selected nodes.
**
native Obj[] selected
**
** Return the expanded state for this node.
**
native Bool isExpanded(Obj node)
**
** Set the expanded state for this node.
**
native Void setExpanded(Obj node, Bool expanded)
**
** Shows the node. If the node is already showing in the
** tree, this method simply returns. Otherwise, the items
** are scrolled and expanded until the node is visible
**
native Void show(Obj node)
**
** Update the entire tree's contents from the model.
**
native Void refreshAll()
**
** Update the specified node from the model.
**
native Void refreshNode(Obj node)
**
** Return the tree node at the specified coordinate relative
** to this widget. Return null if no node at given coordinate.
**
native Obj? nodeAt(Point pos)
}
**************************************************************************
** TreeModel
**************************************************************************
**
** TreeModel models the data of a tree widget.
**
@Js
class TreeModel
{
**
** Get root nodes.
**
virtual Obj[] roots() { [,] }
**
** Get the text to display for specified node.
** Default is 'node.toStr'.
**
virtual Str text(Obj node) { node.toStr }
**
** Get the image to display for specified node or null.
**
virtual Image? image(Obj node) { null }
**
** Get the font for specified node or null for default.
**
virtual Font? font(Obj node) { null }
**
** Get the foreground color for specified node or null for default.
**
virtual Color? fg(Obj node) { null }
**
** Get the background color for specified node or null for default.
**
virtual Color? bg(Obj node) { null }
**
** Return if this has or might have children. This
** is an optimization to display an expansion control
** without actually loading all the children. The
** default returns '!children.isEmpty'.
**
virtual Bool hasChildren(Obj node) { !children(node).isEmpty }
**
** Get the children of the specified node. If no children
** return an empty list. Default behavior is no children.
**
virtual Obj[] children(Obj node) { Obj#.emptyList }
}