Page 1 of 1

TreeGadget with #PB_Tree_ThreeState auto #PB_Tree_Inbetween

Posted: Tue Sep 10, 2013 4:28 pm
by bamsagla
Hi everyone,

as I didn't find anything about modifying the #PB_Tree_Inbetween state of a TreeGadget with the #PB_Tree_ThreeState parameter I tried to patch something that (at least) is working as I would expect. My problem was the (automatic) setting of the #PB_Tree_Inbetween state if I select / deselect one or more sublevel entries in a TreeGadget with some sublevels. So the following code is a sample for setting the correct states for child entries and parent entries over various sublevels inside the TreeGadget.

Apologies for my english, I'm german. Just give the following code a try and you should see what I tried to achieve. It's really clear to me that this code is far away from being optimized because it loops through every entry for every sublevel on every change (click) of the checkboxes of the TreeGadget. Maybe someone has the effort to create an optimized code or maybe there is a better solution somewhere on the forums.

If this code helps someone - feel free to use it for your own projects (without any warranties :P).

Bye, Harry.

Code: Select all

; Expand all entries in the TreeGadget
Procedure Expandall(Gadget.i)
	Counter = CountGadgetItems(Gadget)
	If Counter > 0 : For Looper = 0 To Counter - 1 : SetGadgetItemState(Gadget, Looper, #PB_Tree_Expanded) : Next : EndIf
EndProcedure
	
; Set the correct state in the defined SubLevel of the TreeGadget
Procedure Levelhook(Gadget.i, Level.i)
	Define.i Searcher, Marker, Nomark, Counter, Looper, Actlevel = -1, Between, Child = Level + 1, Done
	Counter = CountGadgetItems(Gadget)
	; Loop through every TreeGadget entry
	For Looper = 0 To Counter
		; Level of the actual entry gets saved
		If Not Counter = Looper : Searcher = GetGadgetItemAttribute(Gadget, Looper, #PB_Tree_SubLevel) : EndIf
		; If the actual level is the defined SubLevel then it gets corrected
		If Searcher = Level Or Counter = Looper
			; If there was a saved defined SubLevel it gets corrected
			If Not Actlevel = -1
				If Marker > 0 And Nomark > 0 : SetGadgetItemState(Gadget, Actlevel, #PB_Tree_Expanded | #PB_Tree_Inbetween) : EndIf
				If Marker > 0 And Nomark = 0 : SetGadgetItemState(Gadget, Actlevel, #PB_Tree_Expanded | #PB_Tree_Checked) : EndIf
				If Marker = 0 And Nomark > 0 : SetGadgetItemState(Gadget, Actlevel, #PB_Tree_Expanded) : EndIf
			EndIf
			; The new defined SubLevel entry gets saved and the markers get resetted
			Actlevel = Looper : Marker = 0 : Nomark = 0
		EndIf
		; If the actual entry is a child entry of the defined SubLevel it gets analyzed
		If Not Counter = Looper
			If Searcher = Child
				Between = GetGadgetItemState(Gadget, Looper)
				Done = 0
				If Between & #PB_Tree_Checked : Marker + 1 : Done = 1 : EndIf
				If Between & #PB_Tree_Inbetween : Marker + 1 : Nomark + 1 : Done = 1 : EndIf
				If Done = 0 : Nomark + 1 : EndIf
			EndIf
		EndIf
	Next
EndProcedure

; The checkboxes of the child entries get corrected
Procedure Sethook(Gadget.i, Entry.i)
	Define.i Counter, Level, Status, Newlev, Looper, Sublev, Mainer = -1, Subber, Marker, Nomark, Statlev
	Counter = CountGadgetItems(Gadget)
	If Counter > 0
		; The current level and status of the clicked entry gets saved
		Level = GetGadgetItemAttribute(Gadget, Entry, #PB_Tree_SubLevel)
		Status = GetGadgetItemState(Gadget, Entry)
		If Status & #PB_Tree_Checked : Status = #PB_Tree_Checked | #PB_Tree_Expanded : Else : Status = #PB_Tree_Expanded : EndIf
		; If there are sublevel (child) entries, they get selected or deselected
		If Counter > Entry
			For Looper = Entry + 1 To Counter - 1
				Newlev = GetGadgetItemAttribute(Gadget, Looper, #PB_Tree_SubLevel)
				; If there is an entry of the same sublevel then we are breaking the loop, otherwise the saved status is set to the entry
				If Newlev <= Level : Break : Else : SetGadgetItemState(Gadget, Looper, Status) : EndIf
			Next
		EndIf
		; Here the entries of the parent sublevels getting set to the corrected status
		If Level > 0 : For Looper = Level - 1 To 0 Step -1 : Levelhook(Gadget, Looper) : Next : EndIf
	EndIf
EndProcedure

; Simple Window with just one TreeGadget
If OpenWindow(0, 0, 0, 640, 480, "TreeGadget ThreeState Checkbox Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
	TreeGadget(0, 10, 10, 600, 400, #PB_Tree_CheckBoxes | #PB_Tree_ThreeState | #PB_Tree_NoButtons)
	
	AddGadgetItem(0, -1, "Main 1", 0, 0)
	AddGadgetItem(0, -1, "Sub 1-1", 0, 1)
	AddGadgetItem(0, -1, "Sub 1-1-1", 0, 2)
	AddGadgetItem(0, -1, "Sub 1-1-2", 0, 2)
	AddGadgetItem(0, -1, "Sub 1-2", 0, 1)
	AddGadgetItem(0, -1, "Sub 1-2-1", 0, 2)
	AddGadgetItem(0, -1, "Sub 1-2-2", 0, 2)
	AddGadgetItem(0, -1, "Main 2", 0, 0)
	AddGadgetItem(0, -1, "Sub 2-1", 0, 1)
	AddGadgetItem(0, -1, "Sub 2-1-1", 0, 2)
	AddGadgetItem(0, -1, "Sub 2-1-2", 0, 2)
	AddGadgetItem(0, -1, "Sub 2-2", 0, 1)
	AddGadgetItem(0, -1, "Sub 2-2-1", 0, 2)
	AddGadgetItem(0, -1, "Sub 2-2-2", 0, 2)
	
	Expandall(0)
	
	Repeat
		
		Select WaitWindowEvent(5000)
				
			Case #PB_Event_CloseWindow : Ending = 1
			Case #PB_Event_Gadget : If EventGadget() = 0 : If EventType() = #PB_EventType_Change : Sethook(0, GetGadgetState(0)) : EndIf : EndIf
				
		EndSelect
		
	Until Ending = 1
EndIf