Page 1 of 1

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

Posted: Mon Sep 14, 2015 8:46 am
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

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

Posted: Mon Sep 14, 2015 9:00 am
by davido
@Keya,
Very neatly done. Thank you for sharing. :D
Makes my own attempt look really shabby. :oops:

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

Posted: Sun Sep 19, 2021 12:45 pm
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.

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

Posted: Sun Sep 19, 2021 1:26 pm
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 

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

Posted: Sun Sep 19, 2021 7:30 pm
by Kwai chang caine
Works nice here :D
Thanks for sharing 8)

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

Posted: Mon Nov 15, 2021 11:49 am
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

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

Posted: Thu Nov 18, 2021 2:30 pm
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.