Tree gadget Select all,Deselect all,Collapse all,Expand all

Share your advanced PureBasic knowledge/code with the community.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Tree gadget Select all,Deselect all,Collapse all,Expand all

Post by Keya »

OS: Windows+Linux+Mac
Respects existing state to combine values (doesn't simply overwrite), so for example if it's collapsed or expanded and you select/deselect it it will stay collapsed/expanded.

[Update] in Windows i think this is possible with a single SendMessage call and using "-1" as the control id - for an example (using listview instead of treeview but probably just requires different variant of the same message) see here

There are just 4 simple functions, but here is a full demo:

Code: Select all

;=====================================================================================================

Procedure TreeExpandAllItems(TreeId)
  Protected CurItem.i, CurState.i, ItemCnt.i = CountGadgetItems(TreeId) 
  If ItemCnt <= 0: ProcedureReturn: EndIf 
  For CurItem = 0 To ItemCnt-1
    CurState = GetGadgetItemState(TreeId, CurItem)
    CurState = CurState ! #PB_Tree_Collapsed
    If CurState & #PB_Tree_Checked
      CurState = #PB_Tree_Checked | #PB_Tree_Expanded
    ElseIf CurState & #PB_Tree_Inbetween
      CurState = #PB_Tree_Inbetween | #PB_Tree_Expanded
    Else
      CurState = #PB_Tree_Expanded
    EndIf
    SetGadgetItemState(TreeId, CurItem, CurState)    
  Next
EndProcedure

Procedure TreeCollapseAllItems(TreeId)
  Protected CurItem.i, CurState.i, ItemCnt.i = CountGadgetItems(TreeId) 
  If ItemCnt <= 0: ProcedureReturn: EndIf 
  For CurItem = 0 To ItemCnt-1
    CurState = GetGadgetItemState(TreeId, CurItem)
    CurState = CurState ! #PB_Tree_Expanded
    If CurState & #PB_Tree_Checked
      CurState = #PB_Tree_Checked | #PB_Tree_Collapsed
    ElseIf CurState & #PB_Tree_Inbetween
      CurState = #PB_Tree_Inbetween | #PB_Tree_Collapsed
    Else
      CurState = #PB_Tree_Collapsed
    EndIf
    SetGadgetItemState(TreeId, CurItem, CurState)    
  Next
EndProcedure

Procedure TreeDeselectAllItems(TreeId)
  Protected CurItem.i, CurState.i, ItemCnt.i = CountGadgetItems(TreeId) 
  If ItemCnt <= 0: ProcedureReturn: EndIf 
  For CurItem = 0 To ItemCnt-1
    CurState = GetGadgetItemState(TreeId, CurItem)
    CurState = CurState ! #PB_Tree_Checked
    SetGadgetItemState(TreeId, CurItem, CurState)
  Next
EndProcedure

Procedure TreeSelectAllItems(TreeId)
  Protected CurItem.i, CurState.i, ItemCnt.i = CountGadgetItems(TreeId) 
  If ItemCnt <= 0: ProcedureReturn: EndIf 
  For CurItem = 0 To ItemCnt-1
    CurState = GetGadgetItemState(TreeId, CurItem)
    CurState = CurState | #PB_Tree_Checked
    SetGadgetItemState(TreeId, CurItem, CurState)
  Next
EndProcedure

;=====================================================================================================


Enumeration FormWindow
  #DlgMain
EndEnumeration

Enumeration FormGadget
  #Tree1
  #btnExpand
  #btnCollapse
  #btnSelect
  #btnDeselect
EndEnumeration

Declare btnExpand(EventType)
Declare btnCollapse(EventType)
Declare btnDeselect(EventType)
Declare btnSelect(EventType)

Procedure OpenDlgMain(x = 0, y = 0, width = 530, height = 370)
  OpenWindow(#DlgMain, x, y, width, height, "Tree Select, Deselect, Expand, Collapse", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_WindowCentered)
  TreeGadget(#Tree1, 0, 0, 530, 330, #PB_Tree_CheckBoxes)
  ButtonGadget(#btnExpand, 60, 340, 80, 20, "Expand all")
  ButtonGadget(#btnCollapse, 150, 340, 80, 20, "Collapse all")
  ButtonGadget(#btnSelect, 290, 340, 80, 20, "Select all")
  ButtonGadget(#btnDeselect, 380, 340, 80, 20, "Deselect all")
EndProcedure

Procedure DlgMain_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
        Case #btnExpand
          btnExpand(EventType())          
        Case #btnCollapse
          btnCollapse(EventType())          
        Case #btnSelect
          btnSelect(EventType())          
        Case #btnDeselect
          btnDeselect(EventType())          
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure


Procedure btnExpand(EventType)
  TreeExpandAllItems(#Tree1)
EndProcedure

Procedure  btnCollapse(EventType)
  TreeCollapseAllItems(#Tree1)
EndProcedure

Procedure  btnDeselect(EventType)
  TreeDeselectAllItems(#Tree1)
EndProcedure

Procedure  btnSelect(EventType)
  TreeSelectAllItems(#Tree1)
EndProcedure


Procedure FillTreeWithDemoItems(TreeId)
  Protected lTreeItem, lRootNode, lSubNode
  For lRootNode = 1 To 3
    AddGadgetItem (TreeId, -1, "Root " + Str(lRootNode) + " <TreeItem index "+Str(lTreeItem)+">", 0, 0)
    lTreeItem + 1
    For lSubNode = 1 To 4
      AddGadgetItem (TreeId, -1, "Subnode " + Str(lSubNode) + " of Root " + Str(lRootNode) + " <TreeItem index "+Str(lTreeItem)+">", 0, 1)
      lTreeItem + 1
    Next
    SetGadgetItemState(TreeId,lTreeItem - lSubNode,#PB_Tree_Expanded)  ;expand the node now we've finished adding to it
  Next lRootNode
EndProcedure


OpenDlgMain()

FillTreeWithDemoItems(#Tree1)

Repeat
  event = WaitWindowEvent()
Until DlgMain_Events(event) = #False
End
Last edited by Keya on Fri Jul 15, 2016 6:58 am, edited 3 times in total.
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Tree gadget Select all,Deselect all,Collapse all,Expand

Post by davido »

@Keya,
Very neatly done. Thank you for sharing. :D
Makes my own attempt look really shabby. :oops:
DE AA EB
BarryG
Addict
Addict
Posts: 3268
Joined: Thu Apr 18, 2019 8:17 am

Re: Tree gadget Select all,Deselect all,Collapse all,Expand all

Post by BarryG »

Keya wrote: Mon Sep 14, 2015 8:46 am[Update] in Windows i think this is possible with a single SendMessage call and using "-1" as the control id - for an example (using listview instead of treeview but probably just requires different variant of the same message) see here
Anyone know if this is the case? I'd like to expand all TreeGadget nodes with a single API SendMessage if possible, rather than iterate through all the items and expanding them one-by-one. Thanks.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4622
Joined: Sun Apr 12, 2009 6:27 am

Re: Tree gadget Select all,Deselect all,Collapse all,Expand all

Post by RASHAD »

Hi BarryG
Next the most simple one
Coded by Inner
Modified by RASHAD

Code: Select all

Procedure TreeViewExpandAll(Gadget.l) 
  hwndTV.l = GadgetID(Gadget)  
  hRoot.l = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_ROOT, 0)  
  hItem.l = hRoot  
  Repeat 
    SendMessage_(hwndTV, #TVM_EXPAND, #TVE_EXPAND, hItem) 
    hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)  
  Until hItem = #Null  
  SendMessage_(hwndTV, #TVM_ENSUREVISIBLE, 0, hRoot) 
EndProcedure

Procedure TreeViewCollapseAll(Gadget.l) 
  hwndTV.l = GadgetID(Gadget)  
  hRoot.l = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_ROOT, 0)  
  hItem.l = hRoot  
  Repeat 
    SendMessage_(hwndTV, #TVM_EXPAND, #TVE_COLLAPSE, hItem) 
    hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)  
  Until hItem = #Null  
  SendMessage_(hwndTV, #TVM_ENSUREVISIBLE, 0, hRoot) 
EndProcedure 

If OpenWindow(0, 0, 0, 400, 400, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 380, 320)
  For a = 0 To 10
    AddGadgetItem (0, -1, "Normal Item "+Str(a), img2, 0);black 
    AddGadgetItem (0, -1, "Node "+Str(a), img0, 0)       ;red=closed green=open
    SetGadgetItemData(0,CountGadgetItems(0)-1,1)
    AddGadgetItem(0, -1, "Sub-Item 1", img2, 1)
    AddGadgetItem(0, -1, "Sub-Item 2", img2, 1)
    AddGadgetItem(0, -1, "Sub-Item 3", img2, 1)
    AddGadgetItem(0, -1, "Sub-Item 4", img2, 1)
    AddGadgetItem (0, -1, "File "+Str(a), img2, 0)
  Next
  
  ButtonGadget(1,10,335,80,24,"Expand")
  ButtonGadget(2,10,360,80,24,"Collapse") 
  Repeat
    Select WaitWindowEvent()
        
      Case #PB_Event_CloseWindow
        Quit = 1
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            TreeViewExpandAll(0)
            
          Case 2
            TreeViewCollapseAll(0)
            
        EndSelect
    EndSelect
  Until Quit = 1
EndIf 
Egypt my love
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Tree gadget Select all,Deselect all,Collapse all,Expand all

Post by Kwai chang caine »

Works nice here :D
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
AZJIO
Addict
Addict
Posts: 1298
Joined: Sun May 14, 2017 1:48 am

Re: Tree gadget Select all,Deselect all,Collapse all,Expand all

Post by AZJIO »

Code: Select all

Procedure TreeViewExpandAll(hCaret)
	Protected hItem, pItem.TVITEMEX
	SendMessage_(htree, #TVM_EXPAND, #TVE_EXPAND, hCaret)
	hItem = SendMessage_(htree, #TVM_GETNEXTITEM, #TVGN_CHILD, hCaret)
	Repeat
		pItem\Mask = #TVIF_CHILDREN
		pItem\hItem = hItem
		SendMessage_(htree, #TVM_GETITEM, 0, @pItem)
		If pItem\cChildren <> 0
			SendMessage_(htree, #TVM_EXPAND, #TVE_EXPAND, hItem)
			TreeViewExpandAll(hItem)
		EndIf
		hItem = SendMessage_(htree, #TVM_GETNEXTITEM, #TVGN_NEXT, hItem)
	Until  hItem = #Null
EndProcedure

Procedure TreeViewCollapseAll(hCaret)
	Protected hItem, pItem.TVITEMEX
	hItem = SendMessage_(htree, #TVM_GETNEXTITEM, #TVGN_CHILD, hCaret)
	Repeat
		pItem\Mask = #TVIF_CHILDREN
		pItem\hItem = hItem
		SendMessage_(htree, #TVM_GETITEM, 0, @pItem)
		If pItem\cChildren <> 0
			TreeViewCollapseAll(hItem)
			SendMessage_(htree, #TVM_EXPAND, #TVE_COLLAPSE, hItem)
		EndIf
		hItem = SendMessage_(htree, #TVM_GETNEXTITEM, #TVGN_NEXT, hItem)
	Until  hItem = #Null
	SendMessage_(htree, #TVM_EXPAND, #TVE_COLLAPSE, hCaret)
EndProcedure

; — — — — — — — — — — — — — — — — — — — — — — — — — — —

Case #mCollapse
	Item = SendMessage_(htree, #TVM_GETNEXTITEM, #TVGN_CARET, 0)
	If Item
		SendMessage_(htree, #WM_SETREDRAW, 0, 0)
		TreeViewCollapseAll(Item)
		SendMessage_(htree, #TVM_ENSUREVISIBLE, 0, Item)
		SendMessage_(htree, #WM_SETREDRAW, 1, 0)
	EndIf
Case #mExpand
	Item = SendMessage_(htree, #TVM_GETNEXTITEM, #TVGN_CARET, 0)
	If Item
		SendMessage_(htree, #WM_SETREDRAW, 0, 0)
		TreeViewExpandAll(Item)
		SendMessage_(htree, #TVM_ENSUREVISIBLE, 0, Item)
		SendMessage_(htree, #WM_SETREDRAW, 1, 0)
	EndIf
User avatar
Lord
Addict
Addict
Posts: 846
Joined: Tue May 26, 2009 2:11 pm

Re: Tree gadget Select all,Deselect all,Collapse all,Expand all

Post by Lord »

@Keya:

In your code

Code: Select all

Procedure TreeDeselectAllItems(TreeId)
  Protected CurItem.i, CurState.i, ItemCnt.i = CountGadgetItems(TreeId) 
  If ItemCnt <= 0: ProcedureReturn: EndIf 
  For CurItem = 0 To ItemCnt-1
    CurState = GetGadgetItemState(TreeId, CurItem)
    CurState = CurState ! #PB_Tree_Checked
    SetGadgetItemState(TreeId, CurItem, CurState)
  Next
EndProcedure
Shouldn't the line

Code: Select all

CurState = CurState ! #PB_Tree_Checked
read

Code: Select all

CurState = CurState & ~#PB_Tree_Checked
else your code toggles between checked and unchecked
erverytime you click on button "Deselect all" and button
"Select all" could be removed.
Image
Post Reply