A pane that displays a tree of items in a "stacked" drawing, where each item has an associated value and child items that represent a fraction of that value. Each item is displayed as a rectangle whose width corresponds to the value. Child items are displayed below the item to make a stack of rectangles.
An object which is the root of the tree of items, or nil
.
A designator for a function of two arguments: the stacked-tree
and an item.
A designator for a function of three arguments: the stacked-tree
, an item and a vector of numbers.
A designator for a function of two arguments: the stacked-tree
and an item.
A designator for a function of two arguments: the stacked-tree
and an item returning a menu-object.
stacked-tree-root
stacked-tree-item-function
stacked-tree-item-menu-function
stacked-tree-empty-tree-string
The class stacked-tree
is a subclass of output-pane, which displays a tree of items in a "stacked" drawing. In a stacked drawing, each item of the tree is represented by a horizontal rectangle. The height of the rectangle is fixed to accommodate the height of the font of the stacked-tree
, while the width corresponds to the "value" of the item. The children of each item are drawn side-by-side below the item itself, to make a stack of rectangles ("stacked").
Within each item's rectangle, the stacked-tree
displays a label, consisting of the item's name (the third value of
item-function
, see below) and the percentage of the item's value with respect to the value of the stacked-tree
. The name and/or percentage are omitted if the rectangle is not wide enough.
root
and
item-function
specify the tree that the stacked-tree
is displaying.
root
can be initialized by the :root
initarg or set by using (setf stacked-tree-root)
or modify-stacked-tree. Likewise,
item-function
can be initialized by the :item-function
initarg or set by using (setf stacked-tree-item-function)
or modify-stacked-tree. The stacked-tree
uses
item-function
to traverse the tree starting from
root
.
item-function
must be a designator for a function with two arguments: the stacked-tree
and an item. It should return three values:
A real
or nil
. If
item-value
is a positive real
, it specifies the item's value, which affects the width of the rectangle used to represent it. If
item-value
is nil
, then the stacked-tree
computes the value as the sum of the values of the
item-children
. If
item-value
is not positive, then the item is ignored.
A list of items that are the children of the item argument. If
item-children
is nil
then the item is a leaf item and has no children.
A string or nil
. When
item-name
is non-nil, the string representation of it (the result of calling the
print-function
inherited from collection) is displayed within the rectangle. Just the rectangle is displayed if
item-name
is nil
.
Both root and elements of item-children returned by item-function can be any object. The only requirement is that item-function returns useful values when called with this object. Thus the tree is completely defined by root and by what item-function returns.
stacked-tree
calls
item-function
on items down the tree until either a leaf item is reached (that is when
item-children
is nil
), or when the depth of the tree reaches
max-level
, if that is non-nil.
Note: Currently there is nothing else to stop the descent down the tree, so you must either have a finite tree, that is your
item-function
must return nil
as the
item-children
at some level on every branch, or you must supply a non-nil
max-level
.
If
value
is non-nil, it specifies the value on which to base the percentage computations when displaying items. If
value
is nil
or not specified, it defaults to the
item-value
of
root
, which is the natural value in many cases, but not always. For example, the Profiler tool in the LispWorks IDE uses a
value
that is the number of times that the profiling was done, while the
item-value
of its
root
is the sum of the number of times that each process was profiled, which will be much larger when you profile more than one process.
color-function or colors specify the background color used for each displayed rectangle.
If
color-function
is non-nil, then
colors
is ignored.
color-function
is called for each item, the first time the item is displayed, with two arguments: the stacked-tree
and the item. It must return a color specification (a color-spec or a recognized symbol, see The Color System), which is then used as the background color of the rectangle for the item.
If
color-function
is nil
, then
colors
is used.
colors
defaults to a plausible list of colors, so it does not need to be specified. If it supplied, it must be a list of color specifications. The stacked-tree
selects a random color from this list for each item the first time the item is displayed.
If
motion-callback
is non-nil, it is called when the user moves the mouse over the stacked-tree
, with three arguments: the stacked-tree
, the item associated with the rectangle at the mouse position or nil
if the mouse is not over any rectangle, and a vector specifying the coordinates of the item (or nil
if the item is nil
). The vector contains eight elements:
x, y, width, height of the item's rectangle in internal coordinates. Note that the rectangle may have only a partial overlap with the visible area, meaning that only part of it is visible.
The horizontal offset in pixels of the beginning of the label from the left side of the rectangle, that is the label's left side is x + label-offset.
The width in pixels that is available to display the label. This is always smaller than the width by a few pixels, and if the rectangle is not visible, may be much smaller or 0.
The width in pixels of the label that should be displayed (as returned by get-string-extent when called with the label).
The width in pixels that is required to display the percentage for the item.
If
highlight
is non-nil, when the user moves the mouse over the stacked-tree
, the rectangle under the mouse is highlighted.
Note: Both
motion-callback
and
highlight
are implemented by defining the :motion
gesture in the
input-model
of the stacked-tree
. If you supply an
input-model
containing :motion
(see output-pane), then this will override the internal one, so
motion-callback
will never be called and
highlight
will not have any effect.
empty-tree-string
, if non-nil, should be a string. The default is "Empty STACKED-TREE displayer". It is displayed in the stacked-tree
if you set
root
to nil
, or when a non-positive
item-value
is returned when
item-function
is called on
root
.
If
item-menu-function
is non-nil, it is called when the context menu needs to be raised (normally by right-click of the mouse), with two arguments: the stacked-tree
and the selected item (or nil
if none is selected). It should return a menu, menu-component or nil
. If
item-menu-function
returns a menu, then it is used as the context menu. If it returns a menu-component, LispWorks makes a menu containing the component followed by the default stacked-tree
menu (described later). If it returns nil
, LispWorks raises the default stacked-tree
menu. If
item-menu-function
is nil
, LispWorks also raises the default stacked-tree
menu.
Note:
item-menu-function
is called from the make-pane-popup-menu method of stacked-tree
. You can completely override this by using the :pane-menu
initarg (see Popup menus for panes), or by defining your own make-pane-popup-menu method specializing on stacked-tree
and your own interface class.
Note: When the menu is raised as a result of a mouse click within a rectangle that is associated with an item then this item is selected while the menu is visible. When the menu has been dismissed, if the contents and the selection of the stacked-tree
are still the same, then the selection goes back to the item that was selected before the mouse click.
Some features of stacked-tree
are inherited from output-pane as described here.
If you supply a
display-callback
then it will be called after the stacked-tree
has drawn what it wants to draw.
If you supply a
resize-callback
, then the stacked-tree
ensures that the selected item is visible after calling your callback.
stacked-tree
forces
coordinate-origin
to be :fixed-graphics
.
The stacked-tree
has default initargs for :draw-with-buffer
, :horizontal-scroll
and :vertical-scroll
(all t
). If you override any of these you will affect its behavior.
The stacked-tree
implements its user input interaction (see below) using the
input-model
of output-pane. If you supply the :input-model
initarg, its value will be appended before the internal input-model of stacked-tree
, so your callbacks will override the internal ones. Note that this affects all interaction, including selection of an item. Your input-model callbacks can use stacked-tree-item-at-point to find the item at the x,y coordinates.
Some features of stacked-tree
are inherited from choice as described here.
The
interaction
of stacked-tree
is always :single-selection
. Setting the
items
signals an error.
choice-selection and choice-selected-item can be used in the usual way, including setting them. When the selection is set, the stacked-tree
ensures that the selected item is visible.
The selection-callback and action-callback (inherited from callbacks) can be used, and are called due to the input-model as described above.
In the following discussion,
root-width
is the width in pixels of the rectangle used to display
root
. Whenever
root
is changed (and initially),
root-width
is set such that width of the rectangle used to display
root
is the visible width of the stacked-tree
.
Moving the mouse over a stacked-tree
calls
motion-callback
if it is non-nil, and highlights the item under the mouse if
highlight
is non-nil.
Left-click selects the item that was clicked.
Left-double-click on a item changes the
root-width
such that the width of the clicked item's rectangle matches the visible width of the stacked-tree
, and scrolls horizontally such that the item's rectangle starts at the left of the stacked-tree
.
Left-click and drag pans the stacked-tree
, scrolling it such that the clicked point follows the mouse.
The arrow keys change the selected item in the direction indicated if possible. The Down
key moves to the first child of the currently selected item (if any). The Left
and Right
keys move to the item at the same depth if there is any, which may be on a completely different branch of the tree.
The following gestures are also available:
Ctrl-+
, Ctrl--
: Zoom in, zoom out.
Zooming increases or decreases the root-width . It does not affect the vertical dimension.
Ctrl-i
, Ctrl-o
: Zoom in and out in large steps.
Zoom like Ctrl-+
and Ctrl--
, but in larger steps.
Return
, Ctrl-Return
: Action callback, alternative action callback.
See callbacks.
Reset the
root-width
to its initial value, so the root of the tree has the visible width of the stacked-tree
at the time it was first displayed, and scroll the root to the left of the stacked-tree
.
Ctrl-b
, Ctrl-f
: Go backwards, Go forwards.
Go to the previous or next state of the display. Whenever the
root-width
changes or the user left-clicks, the stacked-tree
records the current state of the display, including the
root-width
and scroll position. It uses a ring of length 50 for this record. Ctrl-b
and Ctrl-f
rotate around this ring.
Ctrl->
, Ctrl-<
: Increment font size, decrement font size.
Try to increment or decrement the font size by one point, and if this fails then try changing the font size by two points. If the font size changes then the height of the rectangles is adjusted to fit the new font height.
The stacked-tree
context menu contains items to perform the operations listed for keyboard interaction above. It is intended mainly as a way for the user to find the keyboard interaction shortcut. Note that if you override the input-model, and you redefine some of the keys, the menu will be confusing and you should replace it by your own menu.
The stacked-tree
is useful when the values of an item's children sum to the value of the item itself or less. If the values of the children sum to more than the value of the item, they will overflow to the right of the item and clash with the children of the item's next sibling.
The stacked-tree
is used in the
Stacked Tree
tab of the Profiler tool in the LispWorks IDE.
When (setf stacked-tree-root)
or modify-stacked-tree is used to set the
root
of a stacked-tree
that is already displayed, it immediately computes an internal representation by traversing the tree. This means that if the tree is big, this operation may take enough time to cause a noticeable delay.
modify-stacked-tree
stacked-tree-item-at-point
stacked-tree-zoom-by-factor
stacked-tree-width-ratio
stacked-tree-history-backward
stacked-tree-history-backward
stacked-tree-decrease-font-height
stacked-tree-decrease-font-height
stacked-tree-default-color-function
CAPI User Guide and Reference Manual (Macintosh version) - 3 Aug 2017