It’s been several months since my last post. I have taken a new position with an ISV located in Atlanta, Georgia. My new position has afforded me the conundrum of having more to blog about and less time to blog. In the current economic climate one cannot complain about being too busy…better than the alternative.
I came across a simple subject to add to the blog today. The code below contains two simple methods for keeping track of checkboxes within treeviews enclosed in a sample form to illustrate the behavior. This code is reusable and could even be added to a treeview superclass to handle the checking, unchecking, and graying of treeview items on multiple levels. It is really quite simple but is something that can be time consuming if not handled dynamically.
* =======================================================
* Treeview Sample Form
* =======================================================
FUNCTION OPTIONS(*DIRECT)
BEGIN_COM ROLE(*EXTENDS #PRIM_FORM) Clientheight(362) Clientwidth(384) Height(400) Layoutmanager(#ATLM_1) Left(366) Top(132) Width(400)
DEFINE_COM CLASS(#PRIM_TRVW) NAME(#TRVW_1) Componentversion(2) Displayposition(1) Height(362) Keyboardpositioning(SortColumn) Left(0) Managechildren(True) Parent(#COM_OWNER) Tabposition(1) Top(0) Width(384)
DEFINE_COM CLASS(#PRIM_TVCL) NAME(#TVCL_1) Checkboxes(True) Displayposition(1) Keyposition(1) Level(1) Parent(#TRVW_1) Sortposition(1) Source(#STD_CODE)
DEFINE_COM CLASS(#PRIM_TVCL) NAME(#TVCL_2) Checkboxes(True) Displayposition(1) Keyposition(1) Level(2) Parent(#TRVW_1) Sortposition(1) Source(#STD_DESC)
DEFINE_COM CLASS(#PRIM_TVCL) NAME(#TVCL_3) Checkboxes(True) Displayposition(1) Keyposition(1) Level(3) Parent(#TRVW_1) Sortposition(1) Source(#STD_DESCL)
DEFINE_COM CLASS(#PRIM_ATLM) NAME(#ATLM_1)
DEFINE_COM CLASS(#PRIM_ATLI) NAME(#ATLI_1) Attachment(Center) Manage(#TRVW_1) Parent(#ATLM_1)
DEFINE FIELD(#wLevel1) TYPE(*INT)
DEFINE FIELD(#wLevel2) TYPE(*INT)
DEFINE FIELD(#wLevel3) TYPE(*INT)
EVTROUTINE HANDLING(#COM_OWNER.Initialize)
BEGIN_LOOP USING(#wLevel1) TO(3)
#STD_CODE := ’00′ + #wLevel1.AsString
BEGIN_LOOP USING(#wLevel2) TO(3)
#STD_DESC := #STD_CODE + ‘ – Description 0′ + #wLevel2.AsString
BEGIN_LOOP USING(#wLevel3) TO(3)
#STD_DESCL := #STD_DESC + ‘ – Long Description 0′ + #wLevel3.AsString
ADD_ENTRY TO_LIST(#TRVW_1)
#TRVW_1.CurrentItem.Expanded := True
END_LOOP
END_LOOP
END_LOOP
ENDROUTINE
* =======================================================
* Update Treeview Parent/Child Items on Change
* =======================================================
EVTROUTINE HANDLING(#TRVW_1.ItemChanged) OPTIONS(*NOCLEARMESSAGES *NOCLEARERRORS)
* Set Child Items Checkbox State if Current Item has Child Items
IF (#TRVW_1.CurrentItem.HasChildren = ‘YES’)
#COM_OWNER.SetChildCheckBoxes( #TRVW_1.CurrentItem )
ENDIF
* Set Parent Item Checkbox State fif Current Item is Child Item
IF (#TRVW_1.CurrentItem.Level > 1)
#COM_OWNER.SetParentCheckBoxes( #TRVW_1.CurrentItem )
ENDIF
ENDROUTINE
* =======================================================
* Set Parent Item Checkbox State from Child Item
* =======================================================
MTHROUTINE NAME(SetParentCheckboxes)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_TVIT) NAME(#ChildItem) PASS(*BY_REFERENCE)
* Assume All Children are Unchecked
#ChildItem.ParentItem.Checked := False
FOR EACH(#Item) IN(#ChildItem.ParentItem.Items)
IF (#Item.Checked = True)
* Set to Checked if One Child Item is Checked
#Item.ParentItem.Checked := True
LEAVE
ENDIF
ENDFOR
IF (#ChildItem.ParentItem.Checked = True)
FOR EACH(#Item) IN(#ChildItem.ParentItem.Items)
IF ((#Item.Checked = False) *Or (#Item.Checked = Grayed))
* Set to Grayed if One Child Item is Unchecked or Grayed
#Item.ParentItem.Checked := Grayed
LEAVE
ENDIF
ENDFOR
ELSE
FOR EACH(#Item) IN(#ChildItem.ParentItem.Items)
IF (#Item.Checked = Grayed)
* Set to Grayed if One Child Item is Grayed
#Item.ParentItem.Checked := Grayed
LEAVE
ENDIF
ENDFOR
ENDIF
IF (#ChildItem.ParentItem.Level > 1)
* Continue Updating Parent Items until Root Item
#COM_OWNER.SetParentCheckBoxes( #ChildItem.ParentItem )
ENDIF
ENDROUTINE
* =======================================================
* Set Child Item Checkbox State from Parent Item
* =======================================================
MTHROUTINE NAME(SetChildCheckboxes)
DEFINE_MAP FOR(*INPUT) CLASS(#PRIM_TVIT) NAME(#ParentItem) PASS(*BY_REFERENCE)
IF (#ParentItem.Checked <> Grayed)
FOR EACH(#Item) IN(#ParentItem.Items)
* Set Item to Parent Item Checkbox Status if Checked or Unchecked Only
#Item.Checked := #ParentItem.Checked
IF (#Item.HasChildren = ‘YES’)
* Continue Updating Child Items until Lowest Level Reached
#COM_OWNER.SetChildCheckBoxes( #Item )
ENDIF
ENDFOR
ENDIF
ENDROUTINE
END_COM
