TREE

A Tree control looks like a list box except that each "parent item" can have one or more "child items" attached to it. The child items are listed below their parent, indented to the right. When the user double-clicks on a parent item, it alternately expands or collapses (ie, shows or hides) the child items below it. (Also, pressing the ENTER key alternately shows/hides the items). There can be lines showing which child items belong to which parent item, and a button that indicates whether a parent's child items are shown or hidden. A child item can itself have child items, etc.

A TREE with 3 parent items named "Parent 1", "Parent 2", and "Parent 3". "Parent 1" is expanded to show that "Parent 1" has two children named "Child 1 for P1" and "Child 2 for P1". "Child 1 for P1" itself has two children named "Child 1 for C1" and "Child 2 for C1". "Child 2 for C1" is the currently selected item. "Parent 2" has no children. "Parent 3" has children, but they are currently hidden from view (hence the + sign in the button).


Uses

A Tree control is useful for displaying a list of components that may contain sub-components, for example, a directory.


Styles

Shortcut The Shortcut box lets you enter a keyboard shortcut that will automatically select this control whenever the user presses that shortcut.

A TREE may have any, all, or none of the following styles:

BUTTONS Displays a minus or plus button to the left of each parent item which can collapse or expand the parent's child items.
Lines Displays lines linking child items to their corresponding parent items.
Root lines (ROOT) Displays lines linking child items to the root of the hierarchy.
Item label (EDIT) Allows the user to edit the labels of tree view items.
Keep scrollbar (NOSCROLL) Shows a disabled vertical scroll bar for the tree when the tree does not contain enough items to scroll. If you do not specify this style, the scroll bar is hidden when the tree can fully display all items without needing to scroll.
Keep selection (ALWAYS) Always highlights the current selection in the tree, regardless of whether the control has the focus.
No Drag/Drop (NODRAGDROP) The TREE control will not generate a BEGINDRAG event when the user attempts to drag an item from the TREE to somewhere else.
No ToolTips (NOTIPS) The TREE normally provides yellow pop-up tips that display the full name of an item whose name does not fit in the current view. This style disables that behavior.
Get ToolTip text (INFO) The TREE will generate a GETINFOTIP event to obtain tooltip information. Use this to return your own description string rather than accepting the default Tool tip string.
Keep Height (REALHEIGHT) The height of the TREE is exactly the size you specified. Normally, Windows resizes a TREE so that its box won't cut off the text of the last displayed item.
Checkboxes (CHECK) Displays a CHECK box next to each item in the control. Effectively, when set to this style, the control creates and sets a state image list. You must still set and get the item’s check state.
HotTrack (TRACK) Gives the control a visible outline as the pointer passes over it. Also known as hover selection, or hot tracking.
1 node visible (SINGLE) Causes only the selected node to be expanded in the tree. Changing selections collapses any other node but the selected one.
Full row select (ROW) Enables full-row selection. The entire row of the selected item is highlighted and clicking anywhere on an item's row will cause it to be selected.
No Sibling (NOSIBLING) Prevents this control from drawing into any overlapping controls.
Group Marks this control as the first of a group of controls in which the user can move from one control to the next with the arrow keys. All subsequent controls (after this first control) belong to the same group up to the next control that has its GROUP flag set. (ie, One group ends where the next begins). For example, to make a group of radio buttons function properly, the first radio button should have the GROUP style, and the subsequent buttons must not.
Tabstop The user can move to this control using the TAB key.
Disabled Control is initially disabled. You can later enable it with a call to GuiSetCtlPlacement.
Hide Control is hidden. You can later make it visible with a call to GuiSetCtlPlacement.
Border Has a border.


Extra styles

A TREE can have the following extra styles:

LABEL An item is selected or deleted by its name (text), rather than position. It is assumed that each item in the tree will have a unique name.
Quiet Do not report any events for this control.
Modal Frame (MODALFRAME) Has a double border.
Static Edge (STATICEDGE) Has a three-dimensional border intended to be used for windows that do not accept user input.
Client Edge (CLIENTEDGE) Has a 3D look comprised of a border with a sunken edge.
Accept files (FILES) Accepts drag-and-drop files (ie, the DROPFILES event).
Align text right (RIGHT) Gives the control generic right-aligned properties (as opposed to the default of left-aligned properties).
Read right-to-left (RTLREADING) Displays the window text using right-to-left reading order properties (instead of the default of left-to-right).
Left Scrollbar (LEFTBAR) The scroll bar is placed upon the left side of the tree (instead of the right side).
Transparent The control is to be transparent. Any controls that are beneath this one are not obscured.


Events

A TREE generates the following events:

Event name When it occurs
SELCHANGING The user has selected a new item, but the TREE has not yet highlighted his choice. If you handle this event, you can return a 1 to prevent his new selection.
SELCHANGED A new item has been selected (and highlighted).
ITEMEXPANDING The user wants to expand an item, but the TREE has not yet expanded the item.
ITEMEXPANDED An item has been expanded.
BEGINDRAG The user has initiated a drag of one of the items in the TREE with the left mouse button.
BEGINRDRAG The user has initiated a drag of one of the items in the TREE with the right mouse button
DELETEITEM An item is being deleted.
BEGINLABELEDIT The user has started to edit the text for an item. This event happens only for the EDIT style.
ENDLABELEDIT The user has finished editing the text for an item. This event happens only for the EDIT style.
GETDISPINFO Requests that you provide information needed to display or sort an item.
SETDISPINFO A notification that you must update any information you maintain about an item.
GETINFOTIP The TREE is requesting additional text information to be displayed in a ToolTip. This event happens only for the INFO style.
SINGLEEXPAND The user opens or closes a tree item using a single click of the mouse. This event happens only for the SINGLE style.
DRAW Custom drawing may need to be done for the control.
FOCUS The control has received the input focus.
UNFOCUS The control has lost the input focus.
KEYDOWN The user pressed a key while the TREE control has the input focus.
KEYUP The user has released the PAGEUP, PAGEDOWN, HOME, END, or arrow keys.
RETURN The user pressed the ENTER key while the TREE control has the input focus.
CLICK The user has clicked the left mouse button within the control.
DBLCLK The user has double-clicked the left mouse button within the control.
RCLICK The user has clicked the right mouse button within the control.
RDBLCLK The user has double-clicked the right mouse button within the control.
SETCURSOR The control is setting the cursor in response to a SETCURSOR message.


REXX Variable

A TREE must have a REXX variable associated with it. Before opening the window which contains the TREE, you must set this variable's value to the item you wish selected. You select an item by its position in the tree (if not using the LABEL style). Consider this example TREE:

A position is determined by the order that an item appears in the tree. Positions of child items include their parent's position(s). For example, in the above tree, Parent 1 is at position 1, Parent 2 is at position 2, and Parent 3 is at position 3. Child 1 for P1 is at position 1 under Parent 1, so its effective position is '1 1'. In other words, it is the first child item under the first parent item. Note that a space separates an item's position from its parent's position.

Child 2 for P1 is at position 2 under Parent 1, so its effective position is '1 2'.

Child 1 for P1 has two children. Child 1 for C1 is at position 1 under Child 1 for P1, so its effective position is '1 1 1'. Child 2 for C1 is at position 2 under Child 1 for P1, so its effective position is '1 1 2'.

For example, assume that you associate a REXX variable named MyTree with the above TREE control. To indicate the selection, you need to set MyTree to the value '1 1 2':

MyTree = "1 1 2"
As another example, assume you wish to select the second child item under the third parent item in the tree. You would initialize MyTree as so:
MyTree = "3 2"
If using the LABEL style, then you instead select an item by its name (ie, text). For example, here we select Child 1 for C1:
MyTree = "Child 1 for C1"
Note: Each item in the tree must have a unique name when using the LABEL style.

You must also initialize another stem variable to list all of the items that appear in the TREE. This variable is initialized such that a tail name of 1 is assigned the text of the first parent. Subsequent tails starting at 2 are the text for the remaining parent items. For example, if you have a tree with parent items of "Parent 1", "Parent 2" and "Parent 3", and the REXX variable name you supplied is MyTreeItems, then here is the setup:

/* Tree Structure */
MyTreeItems.1 = 'Parent 1'  /* First Parent */
MyTreeItems.2 = 'Parent 2'  /* Second Parent */
MyTreeItems.3 = 'Parent 3'  /* Third Parent */
If a parent has any children, the text for those children are assigned to compound variables where an extra tail is added to the parent's variable name. The extra tail is the child number, starting with 1.

For example, if "Parent 1" had 2 children labeled "Child 1" and "Child 2":

/* Tree Structure */
MyTreeItems.1 = 'Parent 1'  /* First Parent */
MyTreeItems.2 = 'Parent 2'  /* Second Parent */
MyTreeItems.3 = 'Parent 3'  /* Third Parent */

MyTreeItems.1.1 = 'Child 1'  /* First Child for Parent 1 */
MyTreeItems.1.2 = 'Child 2'  /* Second Child for Parent 1 */
A child can itself have children. Like with a parent, you append yet another tail to the child's variable name. As a further example, assume "Child 2" itself had a child labeled "One more":
/* Tree Structure */
MyTreeItems.1 = 'Parent 1'  /* First Parent */
MyTreeItems.2 = 'Parent 2'  /* Second Parent */
MyTreeItems.3 = 'Parent 3'  /* Third Parent */

MyTreeItems.1.1 = 'Child 1'  /* First Child for Parent 1 */
MyTreeItems.1.2 = 'Child 2'  /* Second Child for Parent 1 */

MyTreeItems.1.2.1 = 'One more' /* First Child for Child 2 of Parent 1 */
Note: The tail names you add to the variable coincide with the position of a given item. Remember this helpful hint.

After the parent/child's text, you can also place some other options. You must separate each option from other options using a '|' character. The allowable options can be any of the following:

Option
Meaning
'HIDE' The item's children are initially hidden.

Note: The currently selected item is always shown. (ie, Its parent(s) are expanded).

'BOLD' Makes the text bold-face.

Note: BOLD does not appear to make a difference under certain versions of Windows.

As an example, here we make "Child 2" bold-face:

TREE.1.2 = 'Child 2 | BOLD'
You can reserve an item position, by specifying '|'. For example, here we reserve an item position inbetween the 'Parent 1' and 'Parent 2' items:
/* Tree Structure */
MyTreeItems.1 = 'Parent 1'
MyTreeItems.2 = '|'  /* Reserve this position */
MyTreeItems.3 = 'Parent 2'
MyTreeItems.4 = 'Parent 3'

MyTreeItems.3.1 = 'Child 1'
MyTreeItems.3.2 = 'Child 2'

MyTreeItems.3.2.1 = 'One more'
That means that the positions of the items are as so: 'Parent 1' = 1, 'Parent 2' = 3, 'Child 1' = 3.1, 'Child 2' = 3.2, 'One more' = 3.2.1, and 'Parent 3' = 4. This may be useful if you're going to be changing the tree via GuiAddCtlText, and you have the same item in the both trees at a different position. You can use reserved positions in one tree to align the positioning with the other tree.


Dynamically add/remove a TREE

You can dynamically add a TREE to an already open window by calling GuiAddCtl. You must pass a line that describes the control. The format for this line is:

TREE X, Y, Width, Height, Styles, ExtraStyles, VariableName, Accelerator, Contents
X and Y is the position of the top left corner of the control, relative to the window's top left corner.

Width and Height are the size of the control, in pixels.

Styles and ExtraStyles are those listed above, with each style separated by a | character.

VariableName is the variable name to be associated with the control.

Accelerator is the keyboard shortcut that causes the control to be selected for user input.

Contents is the name of a stem variable that is initialized to the items in the TREE.

Before adding a TREE, you should set its associated REXX variable to either the text of the item you wish selected if using the LABEL style, or its position. You should also initialize the Contents variable to the items in the TREE. For example, here we add a TREE at an X Y position of 10, 10, with a width and height of 100 and 80, with the style BORDER, extra styles of CLIENTEDGE and QUIET, and a REXX Variable name of MyTree. Its items are gotten from the variable named MyTreeItems. We select the item "1 2 1" (ie, First parent, second child, first sub-child).

/* Initialize items in the TREE */
MyTreeItems.1 = 'Parent 1'
MyTreeItems.2 = '|'  /* Reserve this position */
MyTreeItems.3 = 'Parent 2'
MyTreeItems.4 = 'Parent 3'

MyTreeItems.3.1 = 'Child 1'
MyTreeItems.3.2 = 'Child 2'

MyTreeItems.3.2.1 = 'One more'

/* Select item at position "1 2 1" */
MyTree = "1 2 1"

/* Create the TREE */
error = GuiAddCtl("TREE 10,10,100,80, BORDER, CLIENTEDGE|QUIET, MyTree, MyTreeItems")
Note: If you wish the TREE to have no selected item, then either DROP its associated variable, or set the variable to an empty string.

You can dynamically remove a TREE by calling GuiRemoveCtl. Here we remove the above TREE:

error = GuiRemoveCtl("MyTree")

Change the items in a tree

You can dynamically change the items in a TREE by calling GuiAddCtlText. You pass the quoted name of the REXX variable associated with the TREE. You also pass the quoted name of a stem variable that has been initialized to all of the items in the tree, as discussed above. Note that if you are reusing a stem variable that you previously used, a good idea is to first DROP that stem to clear out any old items.

/* Initialize 3 items in MyTreeItems. */
DROP MyTreeItems.
MyTreeItems.1 = "This is item 1."
MyTreeItems.2 = "This is item 2."
MyTreeItems.3 = "This is item 3."

/* Set MyTree's contents to the above 3 items. */
GuiAddCtlText("MyTree", "MyTreeItems")
Note: All items previously in the tree are cleared out.


Delete items from a tree

You can delete an item by calling GuiRemoveCtlText. You pass the quoted name of the REXX variable associated with the TREE. You also pass either the text of the item you wish to delete if using the LABEL style, or pass the position of the item. Here we delete the item at position "1 2" from MyTree:

error = GuiRemoveCtlText("MyTree", "1 2")
To delete the currently selected item from the list, then call GuiRemoveCtlText, and pass an empty string for the item to delete:
error = GuiRemoveCtlText("MyTree", "")
To delete all items from the tree (ie, clear out the tree), then call GuiRemoveCtlText, and pass only the name of the variable associated with the control:
error = GuiRemoveCtlText("MyTree")


Selecting an item

To select an item, first set the associated REXX variable to the text of the desired item if using the LABEL style, or the position of the desired item. Then call GuiSetCtlValue, passing that quoted variable name. Here we select the item "Parent 1" (ie, assuming LABEL style):

MyTree = "Parent 1"
GuiSetCtlValue("MyTree")
To unselect all items from a list, DROP the variable:
DROP MyTree
GuiSetCtlValue("MyTree")
Alternately, you can set the variable to an empty string:
MyTree = ""
GuiSetCtlValue("MyTree")


Querying the selected item

To determine which item has been selected, call GuiGetCtlValue. This will set its associated REXX variable to the control's current selection. For example, here we query the above control's selection:
error = GuiGetCtlValue("MyTree")
IF error == "" THEN SAY "Selected item:" MyTree
Note: If there's no selection, then the rexx variable is DROP'ed:
error = GuiGetCtlValue("MyTree")
IF error == "" THEN DO
   IF EXISTS("MyTree") THEN SAY "Selected item:" MyTree
   ELSE SAY "No selection"
END


Allow the user to edit items

If the EDIT style is used, the user can click once upon an item to edit its text. An ENTRY will appear in the place where the item's text is displayed, and the user can type new text. When he presses ENTER, the item's text is changed to his entered text. If the 'QUIET' style is not used, then an ENDLABELEDIT event occurs.