Language > Widgets > About Tree Widgets > Using_Tree_Widget_Checkboxes

# Using Tree Widget Checkboxes

You can create checkboxes on tree widgets with the WIDGET_TREE function, using the CHECKBOX keyword. To control the state of the checkboxes, use the CHECKED keyword. The following image shows checked nodes in tree widget nodes. The filled-in squares next to folders indicate a mixed check state, where some child nodes of the folder are checked and some are not.

## Checkbox Example

This example demonstrates a simple tree with checkboxes on some of its nodes. The tree root's event handler adds business logic to set the state of a node's descendants and ancestors. Checking a folder node sets all child nodes to "checked". Unchecking a node changes all ancestors to either "unchecked" or "mixed", depending on the state of other nodes.

; This routine sets all descendants of a node

; to the given check state.

PRO MY_TREE_UPDATE_DESCENDANTS, node, state

COMPILE_OPT IDL2

; Get an array of all child nodes.

children = WIDGET_INFO( node, /ALL_CHILDREN )

IF ( children[0] EQ 0 ) THEN RETURN

; Set the check-state of each child and then recursively

; update their children

FOREACH c, children DO BEGIN

WIDGET_CONTROL, c, SET_TREE_CHECKED = state

MY_TREE_UPDATE_DESCENDANTS, c, state

ENDFOREACH

END

; This routine sets the check state of all tree widget ancestors of a

; node. The main rule is that if all children are checked or

; all are unchecked then the parent gets the check-state of the

; children. If at least one, but not all, children are unchecked

; or mixed then the parent gets the state of mixed.

PRO MY_TREE_UPDATE_ANCESTORS, node

COMPILE_OPT IDL2

; Get the parent and proceed only if it is a tree widget

parent = WIDGET_INFO( node, /parent )

IF ( parent NE 0 AND WIDGET_INFO( parent, /type ) EQ 11 ) THEN BEGIN

; Get statistics on the children:

; - number of children that are checked (value of 1)

; - number of children that are mixed (value of 2)

; - total number of children of any state

children = WIDGET_INFO( parent, /all_children )

nOnes = TOTAL( WIDGET_INFO( children, /TREE_CHECKED ) eq 1 )

nTwos = TOTAL( WIDGET_INFO( children, /TREE_CHECKED ) eq 2 )

nChildren = N_ELEMENTS( children )

; Figure out the state of the parent node

IF ( nOnes EQ nChildren ) THEN BEGIN

newState = 1

ENDIF ELSE IF ( nOnes GE 1 || nTwos GE 1 ) THEN BEGIN

newState = 2

ENDIF ELSE BEGIN

newState = 0

ENDELSE

; Apply the new state and recursively repeat on the next ancestor

WIDGET_CONTROL, parent, SET_TREE_CHECKED = newState

MY_TREE_UPDATE_ANCESTORS, parent

ENDIF

END

; Create the event handlers

PRO TREE_CHECKBOX_EXAMPLE_EVENT, e

END

PRO HANDLE_TREE_EVENT, e

COMPILE_OPT IDL2

HELP, e, /STRUCTURE

IF ( e.type EQ 2 ) THEN BEGIN

MY_TREE_UPDATE_DESCENDANTS, e.id, e.state

MY_TREE_UPDATE_ANCESTORS, e.id

ENDIF

END

; This is the widget creation routine

PRO TREE_CHECKBOX_EXAMPLE

COMPILE_OPT IDL2

; Create a top level base

topLevelBase = WIDGET_BASE( $

XOFFSET = 200, YOFFSET = 100 )

; Create the tree

root = WIDGET_TREE( topLevelBase, $

event_pro = 'HANDLE_TREE_EVENT' )

; Create the first folder without a checkbox

f1 = WIDGET_TREE( ROOT, /FOLDER, /EXPANDED, VALUE = 'Folder 1' )

; Create the nodes with checkboxes.

; Check some of the boxes (CHECKED = 1)

n11 = WIDGET_TREE( f1, VALUE = 'Node 11', /CHECKBOX, CHECKED = 0 )

n12 = WIDGET_TREE( f1, VALUE = 'Node 12', /CHECKBOX, CHECKED = 1 )

n13 = WIDGET_TREE( f1, VALUE = 'Node 13', /CHECKBOX, CHECKED = 0 )

n14 = WIDGET_TREE( f1, VALUE = 'Node 14', /CHECKBOX, CHECKED = 1 )

; Create the second folder and child nodes with checkboxes.

; Checkboxes are not checked on creation.

f2 = WIDGET_TREE( ROOT, /FOLDER, /EXPANDED, /CHECKBOX, VALUE = 'Folder 2' )

n21 = WIDGET_TREE( f2, VALUE = 'Node 21' )

f22 = WIDGET_TREE( f2, /FOLDER, VALUE = 'Folder 22' )

n221 = WIDGET_TREE( f22, VALUE = 'Node 221' )

n222 = WIDGET_TREE( f22, VALUE = 'Node 222' )

n23 = WIDGET_TREE( f2, VALUE = 'Node 23' )

; Realize the widgets

WIDGET_CONTROL, topLevelBase, /REALIZE

XMANAGER, 'TREE_CHECKBOX_EXAMPLE', topLevelBase, /NO_BLOCK

END