Page 1 of 1

[Solved] Get TreeGadget final text?

Posted: Sat Jun 17, 2023 1:54 pm
by BarryG
See the following image and code... say I click on "File4421" - how can I know that its full path is "Folder 4\Sub-folder 42\Sub-folder 421\File 4421" ?

Assume that I haven't created an array like in the example, and that the items were added manually by someone, one at a time. Thanks!

Image

Code: Select all

Dim f$(14)
f$(1)="Folder 1\File 11"
f$(2)="Folder 1\File 12"
f$(3)="Folder 1\File 13"
f$(4)="Folder 2\File 21"
f$(5)="Folder 2\File 22"
f$(6)="Folder 2\File 23"
f$(7)="Folder 3\File 31"
f$(8)="Folder 3\Sub-folder 3\File 331"
f$(9)="Folder 3\Sub-folder 3\File 332"
f$(10)="Folder 3\Sub-folder 3\File 333"
f$(11)="Folder 4\File 41"
f$(12)="Folder 4\Sub-folder 41\File 441"
f$(13)="Folder 4\Sub-folder 42\Sub-folder 421\File 4421"
f$(14)="Folder 4\File 42"

Procedure FillTreeGadget(Gadget, Array Files.s(1)) ; https://www.purebasic.fr/english/viewtopic.php?p=602949#p602949
  Protected fn.s, currdir.s, idx, count, level, cnt  
  Dim lastdir.s(0) 
  count = ArraySize(Files()) 
  For idx = 1 To count
    fn = Files(idx) 
    cnt = CountString(fn, #PS$) 
    For level = 0 To cnt - 1
      currdir = StringField(fn, level+1, #PS$) 
      If lastdir(level) <> currdir 
        AddGadgetItem(0, -1, currdir, 0, level) 
        lastdir(level) = currdir 
        ReDim lastdir(level+1) 
      EndIf 
    Next 
    fn = StringField(fn, level+1, #PS$) 
    AddGadgetItem(0, -1, fn, 0, level)
  Next
  Dim lastdir(0) 
EndProcedure 

If OpenWindow(0, 0, 0, 355, 400, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 340, 380)   ; TreeGadget standard
  FillTreeGadget(0, f$())
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: Get TreeGadget final text

Posted: Sat Jun 17, 2023 2:35 pm
by Axolotl
hi BarryG,
please try this procedure ....

Code: Select all

Procedure.s GetEntirePath(Gadget, Position) 
  Protected result.s, item, level, lastlevel  

  If Position > -1 
    result = GetGadgetItemText(Gadget, Position)  ; the selected item 
    lastlevel = GetGadgetItemAttribute(Gadget, Position, #PB_Tree_SubLevel)

    For item = Position To 0 Step -1 ; count backwards from selected item
      level = GetGadgetItemAttribute(Gadget, item, #PB_Tree_SubLevel) 
      If level < lastlevel 
        lastlevel = level 
        result = GetGadgetItemText(Gadget, item) + #PS$ + result 
      EndIf
    Next
  EndIf 
  ProcedureReturn result 
EndProcedure


okay, I changed the main loop to this

Code: Select all

If OpenWindow(0, 0, 0, 355, 400, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 340, 380)   ; TreeGadget standard
  FillTreeGadget(0, f$())
  Repeat 
    Select WaitWindowEvent() 
      Case #PB_Event_CloseWindow 
        Break ; say good bye 
      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case 0 
            Debug "" + GetEntirePath(0, GetGadgetState(0)) 
        EndSelect 
    EndSelect 
  ForEver 
EndIf

Re: Get TreeGadget final text

Posted: Sun Jun 18, 2023 1:35 am
by BarryG
Thanks, Axolotl! It was nice to wake up to your solution. Seems like this sort of thing should have a command in PureBasic.

The final working example:

Code: Select all

Dim f$(14)
f$(1)="Folder 1\File 11"
f$(2)="Folder 1\File 12"
f$(3)="Folder 1\File 13"
f$(4)="Folder 2\File 21"
f$(5)="Folder 2\File 22"
f$(6)="Folder 2\File 23"
f$(7)="Folder 3\File 31"
f$(8)="Folder 3\Sub-folder 3\File 331"
f$(9)="Folder 3\Sub-folder 3\File 332"
f$(10)="Folder 3\Sub-folder 3\File 333"
f$(11)="Folder 4\File 41"
f$(12)="Folder 4\Sub-folder 41\File 441"
f$(13)="Folder 4\Sub-folder 42\Sub-folder 421\File 4421"
f$(14)="Folder 4\File 42"

Procedure FillTreeGadget(Gadget, Array Files.s(1))
  Protected fn.s, currdir.s, idx, count, level, cnt  
  Dim lastdir.s(0) 
  count = ArraySize(Files()) 
  For idx = 1 To count
    fn = Files(idx) 
    cnt = CountString(fn, #PS$) 
    For level = 0 To cnt - 1
      currdir = StringField(fn, level+1, #PS$) 
      If lastdir(level) <> currdir 
        AddGadgetItem(0, -1, currdir, 0, level) 
        lastdir(level) = currdir 
        ReDim lastdir(level+1) 
      EndIf 
    Next 
    fn = StringField(fn, level+1, #PS$) 
    AddGadgetItem(0, -1, fn, 0, level)
  Next
  Dim lastdir(0) 
EndProcedure 

Procedure.s GetEntirePath(Gadget, Position) 
  Protected result.s, item, level, lastlevel  
  If Position > -1 
    result = GetGadgetItemText(Gadget, Position)  ; the selected item 
    lastlevel = GetGadgetItemAttribute(Gadget, Position, #PB_Tree_SubLevel)
    For item = Position To 0 Step -1 ; count backwards from selected item
      level = GetGadgetItemAttribute(Gadget, item, #PB_Tree_SubLevel) 
      If level < lastlevel 
        lastlevel = level 
        result = GetGadgetItemText(Gadget, item) + #PS$ + result 
      EndIf
    Next
  EndIf 
  ProcedureReturn result 
EndProcedure

If OpenWindow(0, 0, 0, 355, 400, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 340, 380)
  FillTreeGadget(0, f$())
  Repeat 
    Select WaitWindowEvent() 
      Case #PB_Event_CloseWindow 
        Break
      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case 0 
            Debug "" + GetEntirePath(0, GetGadgetState(0)) 
        EndSelect 
    EndSelect 
  ForEver 
EndIf

Re: [Solved] Get TreeGadget final text?

Posted: Sun Jun 18, 2023 3:37 am
by idle
you can simplify that a bit

Code: Select all

Dim f$(14)
f$(1)="Folder 1\File 11"
f$(2)="Folder 1\File 12"
f$(3)="Folder 1\File 13"
f$(4)="Folder 2\File 21"
f$(5)="Folder 2\File 22"
f$(6)="Folder 2\File 23"
f$(7)="Folder 3\File 31"
f$(8)="Folder 3\Sub-folder 3\File 331"
f$(9)="Folder 3\Sub-folder 3\File 332"
f$(10)="Folder 3\Sub-folder 3\File 333"
f$(11)="Folder 4\File 41"
f$(12)="Folder 4\Sub-folder 41\File 441"
f$(13)="Folder 4\Sub-folder 42\Sub-folder 421\File 4421"
f$(14)="Folder 4\File 42"

Procedure FillTreeGadget(Gadget, Array Files.s(1))
  Protected fn.s, currdir.s, idx,idx1, count, level, cnt  
  
  Dim lastdir.s(0) 
  count = ArraySize(Files()) 
  For idx = 1 To count
    fn = Files(idx) 
    cnt = CountString(fn, #PS$) 
    For level = 0 To cnt - 1
      currdir = StringField(fn, level+1, #PS$) 
      If lastdir(level) <> currdir 
        AddGadgetItem(0, idx1, currdir, 0, level) 
        idx1+1 
        lastdir(level) = currdir 
        ReDim lastdir(level+1) 
      EndIf 
    Next 
    fn = StringField(fn, level+1, #PS$) 
    AddGadgetItem(0, idx1, fn, 0, level)
    SetGadgetItemData(gadget,idx1,idx)
    idx1+1
  Next
  Dim lastdir(0) 
EndProcedure 

If OpenWindow(0, 0, 0, 355, 400, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 340, 380)
  FillTreeGadget(0, f$())
  Repeat 
    Select WaitWindowEvent() 
      Case #PB_Event_CloseWindow 
        Break
      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case 0 
            If EventType() = #PB_EventType_LeftClick  
              out.s = f$(GetGadgetItemData(EventGadget(),GetGadgetState(0)))
              If out <> "" 
                Debug out 
              EndIf   
            EndIf   
          EndSelect 
    EndSelect 
  ForEver 
EndIf


Re: [Solved] Get TreeGadget final text?

Posted: Sun Jun 18, 2023 5:45 am
by AZJIO
Windows only

Code: Select all

EnableExplicit

Dim f$(14)
f$(1)="Folder 1\File 11"
f$(2)="Folder 1\File 12"
f$(3)="Folder 1\File 13"
f$(4)="Folder 2\File 21"
f$(5)="Folder 2\File 22"
f$(6)="Folder 2\File 23"
f$(7)="Folder 3\File 31"
f$(8)="Folder 3\Sub-folder 3\File 331"
f$(9)="Folder 3\Sub-folder 3\File 332"
f$(10)="Folder 3\Sub-folder 3\File 333"
f$(11)="Folder 4\File 41"
f$(12)="Folder 4\Sub-folder 41\File 441"
f$(13)="Folder 4\Sub-folder 42\Sub-folder 421\File 4421"
f$(14)="Folder 4\File 42"

Global TVI.TVITEMEX, Text$, hItem, Gadget, Buffer$
Buffer$ = Space(4096)
With TVI
	\mask = #TVIF_TEXT
	\cchTextMax = 4096
	\pszText = @Buffer$
EndWith

Procedure FillTreeGadget(Gadget, Array Files.s(1))
	Protected fn.s, currdir.s, idx,idx1, count, level, cnt
	
	Dim lastdir.s(0)
	count = ArraySize(Files())
	For idx = 1 To count
		fn = Files(idx)
		cnt = CountString(fn, #PS$)
		For level = 0 To cnt - 1
			currdir = StringField(fn, level+1, #PS$)
			If lastdir(level) <> currdir
				hItem = AddGadgetItem(0, idx1, currdir, 0, level)
				idx1+1
				lastdir(level) = currdir
				ReDim lastdir(level+1)
			EndIf
		Next
		fn = StringField(fn, level+1, #PS$)
		AddGadgetItem(0, idx1, fn, 0, level)
		idx1+1
	Next
	Dim lastdir(0)
EndProcedure

If OpenWindow(0, 0, 0, 355, 400, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	TreeGadget(0, 10, 10, 340, 380)
	FillTreeGadget(0, f$())
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_CloseWindow
				Break
			Case #PB_Event_Gadget
				Select EventGadget()
					Case 0
						If EventType() = #PB_EventType_LeftDoubleClick
							If GetGadgetState(Gadget) <> -1
								Text$ = ""
								Text$ + GetGadgetItemText(Gadget, GetGadgetState(Gadget))
								hItem = SendMessage_(GadgetID(Gadget), #TVM_GETNEXTITEM, #TVGN_CARET, 0)
								Repeat
									hItem = SendMessage_(GadgetID(Gadget), #TVM_GETNEXTITEM, #TVGN_PARENT, hItem)
									If Not hItem
										Break
									EndIf
									; Debug hItem
									With TVI
										\hItem = hItem
									EndWith
									SendMessage_(GadgetID(Gadget), #TVM_GETITEMW, 0, TVI)
									; Debug "-" + Buffer$
									Text$ = Buffer$ + "\" + Text$
								ForEver
								Debug Text$
							EndIf
						EndIf
				EndSelect
		EndSelect
	ForEver
EndIf

Re: [Solved] Get TreeGadget final text?

Posted: Sun Jun 18, 2023 1:46 pm
by Axolotl
Okay, if you need a different separator I recommend this improvement.

Code: Select all

Procedure.s GetEntirePath(Gadget, Position, Sep.s=#PS$)   
  Protected result.s, item, level, lastlevel  

  If Position > -1 
    result = GetGadgetItemText(Gadget, Position)  ; the selected item 
    lastlevel = GetGadgetItemAttribute(Gadget, Position, #PB_Tree_SubLevel)

    For item = Position To 0 Step -1 ; count backwards from selected item
      level = GetGadgetItemAttribute(Gadget, item, #PB_Tree_SubLevel) 
      If level < lastlevel 
        lastlevel = level 
        result = GetGadgetItemText(Gadget, item) + Sep + result 
      EndIf
    Next
  EndIf 
  ProcedureReturn result 
EndProcedure 

And yes, some built-in functions for TreeGadget() would be really great.