TreeGadget collapse nodes

Just starting out? Need help? Post your questions and find answers here.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

TreeGadget collapse nodes

Post by collectordave »

Hi All

Here is some code from the help.

Code: Select all

  If OpenWindow(0, 0, 0, 355, 180, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    TreeGadget(0, 10, 10, 160, 160)                                         ; TreeGadget standard
    TreeGadget(1, 180, 10, 160, 160, #PB_Tree_CheckBoxes | #PB_Tree_NoLines)  ; TreeGadget with Checkboxes + NoLines
    For ID = 0 To 1
      For a = 0 To 10
        AddGadgetItem (ID, -1, "Normal Item "+Str(a), 0, 0) ; if you want to add an image, use
        AddGadgetItem (ID, -1, "Node "+Str(a), 0, 0)        ; ImageID(x) as 4th parameter
        AddGadgetItem(ID, -1, "Sub-Item 1", 0, 1)    ; These are on the 1st sublevel
        AddGadgetItem(ID, -1, "Sub-Item 2", 0, 1)
        AddGadgetItem(ID, -1, "Sub-Item 3", 0, 1)
        AddGadgetItem(ID, -1, "Sub-Item 4", 0, 1)
        AddGadgetItem (ID, -1, "File "+Str(a), 0, 0) ; sublevel 0 again
      Next
    Next
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
I am trying to only have one node open at ny one time.

So if you select Node 0 it expands then if you select Node 1 node 0 collapses and node 1 expands.

Going round in circles.

Cross platform if possible!
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: TreeGadget collapse nodes

Post by mk-soft »

Since the TreeGadget can change the status of each item without changing the selection, I created my own event. For this the last state of the item is stored in item data.

Update
- BindEvent not work perfectly on macOS and Linux

Update
- Change to EventTypes

Update v1.03.0
- Reduze call of check tree gadget

Update v1.04.1
- macOS Notification

Code: Select all

;-TOP
; New EventType for TreeGadgets by mk-soft, v1.04.1, Update 28.02.2021

EnableExplicit

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  
  ;- MacOS SetNotificationCallback
  
  ImportC ""
    sel_getName(selector)
    sel_registerName(str.p-utf8)
    class_addMethod(class, selector, imp, types.p-utf8)
  EndImport
  
  ; *** required variables ***
  Global notificationCenter = CocoaMessage(0, 0, "NSNotificationCenter defaultCenter")
  Global appDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
  Global delegateClass = CocoaMessage(0, appDelegate, "class")
  
  Structure udtCallbackEntry
    Window.i
    Gadget.i
  EndStructure  
  
  Global NewMap CallbackEntry.udtCallbackEntry()
  
  ; *** Callback (Base by Shardik) ***
  
  Procedure SetGadgetCallback(GadgetID.I, GadgetCallback.I, Method.S)
    Protected PlaceholderList.S
  
    PlaceholderList = LSet("@:", CountString(Method, ":"), "@")
    class_addMethod_(delegateClass, sel_registerName_(Method), GadgetCallback, PlaceholderList)
    CocoaMessage(0, GadgetID(GadgetID), "setDelegate:", appDelegate)
  EndProcedure
  
  ; *** Notification (Base by Shardik) ***
  
  Procedure SetNotificationCallback(Window, Gadget, *Callback, Notification.s)
    Protected selector
    
    AddMapElement(CallbackEntry(), Str(GadgetID(Gadget)))
    CallbackEntry()\Window = Window
    CallbackEntry()\Gadget = Gadget
    
    selector = sel_registerName("CB_" + Str(*Callback))
    class_addMethod(delegateClass, selector, *Callback, "v@:@")
    CocoaMessage(0, notificationCenter,
                 "addObserver:", appDelegate, 
                 "selector:", selector,
                 "name:$", @Notification,
                 "object:", GadgetID(Gadget))
  
  EndProcedure
  
  Procedure RemoveNotificationCallback(Window, Gadget, *Callback, Notification.s)
    CocoaMessage(0, notificationCenter,
                 "removeObserver:", appDelegate,
                 "name:$", @Notification,
                 "object:", GadgetID(Gadget))
  EndProcedure
  
  ; *** Cocoa String Helper ***
  
  Macro CocoaString(NSString)
    PeekS(CocoaMessage(0, NSString, "UTF8String"), -1, #PB_UTF8)
  EndMacro

CompilerEndIf

; ********


Enumeration #PB_EventType_FirstCustomValue
  #MyEventType_Tree_Expanded
  #MyEventType_Tree_Collapsed
EndEnumeration

Procedure InitTreeGadgetData(Gadget)
  Protected item, cnt
  cnt = CountGadgetItems(Gadget) - 1
  For item = 0 To cnt
    SetGadgetItemData(Gadget, item, GetGadgetItemState(Gadget, item))
  Next
EndProcedure

Procedure CheckTreeGadget(Gadget)
  Protected item, cnt, state, last_state
  
  If GadgetType(Gadget) = #PB_GadgetType_Tree
    cnt = CountGadgetItems(Gadget) - 1
    For item = 0 To cnt
      state = GetGadgetItemState(Gadget, item)
      last_state = GetGadgetItemData(Gadget, item)
      SetGadgetItemData(Gadget, item, state)
      ; New EventTypes
      If (state & #PB_Tree_Expanded) And Not (last_state & #PB_Tree_Expanded)
        PostEvent(#PB_Event_Gadget, EventWindow(), Gadget, #MyEventType_Tree_Expanded, item)
      EndIf
      If (state & #PB_Tree_Collapsed) And Not (last_state & #PB_Tree_Collapsed)
        PostEvent(#PB_Event_Gadget, EventWindow(), Gadget, #MyEventType_Tree_Collapsed, item)
      EndIf
    Next
  EndIf
EndProcedure

Procedure DoGadgetEvent()
  Protected Gadget
  Protected item, cnt, state, last_state
  
  Gadget = EventGadget()
  If GadgetType(Gadget) = #PB_GadgetType_Tree
    CheckTreeGadget(gadget)
  EndIf
EndProcedure

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  
  Procedure NotificationCallback(*Object, Selector, Notification)
    Protected Notify.s, GadgetID, Gadget
    
    GadgetID = CocoaMessage(0, Notification, "object")
    Notify.s = CocoaString(CocoaMessage(0, Notification, "name"))
    
    Gadget = CallbackEntry(Str(GadgetID))\Gadget
    
    ;Debug "Selector " + PeekS(sel_getName(Selector), -1, #PB_UTF8)
    ;Debug "Gadget " + Gadget
    ;Debug "Notify " + Notify
    
    Select Notify
      Case "NSOutlineViewItemDidExpandNotification"
        CheckTreeGadget(Gadget)
        
      Case "NSOutlineViewItemDidCollapseNotification"
        CheckTreeGadget(Gadget)
        
    EndSelect
    
  EndProcedure

CompilerEndIf

; *****

CompilerIf #PB_Compiler_IsMainFile
    
  Procedure UpdateTreeGadget(Gadget, Item)
    Protected count, i
    count = CountGadgetItems(Gadget) - 1
    For i = 0 To count
      If i <> item
        If GetGadgetItemState(Gadget, i) & #PB_Tree_Expanded
          SetGadgetItemState(Gadget, i, #PB_Tree_Collapsed)
        EndIf
      EndIf
    Next
  EndProcedure
  
  Define ID, a, cnt
  
  If OpenWindow(0, 0, 0, 600, 500, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    TreeGadget(0, 5, 5, 290, 490)                                         ; TreeGadget standard
    TreeGadget(1, 300, 5, 290, 490, #PB_Tree_CheckBoxes | #PB_Tree_NoLines); TreeGadget with Checkboxes + NoLines
    
    For ID = 0 To 1
      For a = 0 To 10
        AddGadgetItem (ID, -1, "Normal Item "+Str(a), 0, 0) ; if you want to add an image, use
        AddGadgetItem (ID, -1, "Node "+Str(a), 0, 0)        ; ImageID(x) as 4th parameter
        AddGadgetItem(ID, -1, "Sub-Item 1", 0, 1)           ; These are on the 1st sublevel
        AddGadgetItem(ID, -1, "Sub-Item 2", 0, 1)
        AddGadgetItem(ID, -1, "Sub-Item 3", 0, 1)
        AddGadgetItem(ID, -1, "Sub-Item 4", 0, 1)
        AddGadgetItem (ID, -1, "File "+Str(a), 0, 0) ; sublevel 0 again
      Next
    Next
    
    InitTreeGadgetData(0)
    InitTreeGadgetData(1)
    
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      BindEvent(#PB_Event_Gadget, @DoGadgetEvent())
    CompilerEndIf
    
    CompilerIf #PB_Compiler_OS = #PB_OS_Linux
      BindEvent(#PB_Event_Gadget, @DoGadgetEvent())
    CompilerEndIf
    
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      SetNotificationCallback(0, 0, @NotificationCallback(), "NSOutlineViewItemDidExpandNotification")
      SetNotificationCallback(0, 0, @NotificationCallback(), "NSOutlineViewItemDidCollapseNotification")
      SetNotificationCallback(0, 1, @NotificationCallback(), "NSOutlineViewItemDidExpandNotification")
      SetNotificationCallback(0, 1, @NotificationCallback(), "NSOutlineViewItemDidCollapseNotification")
    CompilerEndIf
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0, 1
              Select EventType()
                Case #MyEventType_Tree_Expanded
                  Debug "Gadget " + EventGadget() + " Item " + EventData() + " Expanded"
                  UpdateTreeGadget(EventGadget(), EventData())
                  
                Case #MyEventType_Tree_Collapsed
                  Debug "Gadget " + EventGadget() + " Item " + EventData() + " Collapsed"
                  
                Case #PB_EventType_Change
                  ; Debug "Gadget " + EventGadget() + " Item " + GetGadgetState(EventGadget()) + " Selected"
              EndSelect
              
          EndSelect
          
        Default
          
      EndSelect
      
    ForEver
    
  EndIf
  
CompilerEndIf
Last edited by mk-soft on Sun Feb 28, 2021 7:16 pm, edited 3 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: TreeGadget collapse nodes

Post by collectordave »

Brilliant works straight out of the box.

If I am understanding this correctly the problem is that the tree gadget does not always report a mouse click event when the mouse is clicked and does not report a changed event when a node is expanded or collapsed?

Is this a bug with the documentation or should it be a feature request?

Regards

CD
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: TreeGadget collapse nodes

Post by RASHAD »

Hi
The next snippet maybe it's cross platform
I tested it only with PB 5.73 x86 - Windows 10 x64

Code: Select all


If OpenWindow(0, 0, 0, 400, 600, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 380, 580)
  For a = 0 To 10
    AddGadgetItem (0, -1, "Normal Item "+Str(a), 0, 0)
    AddGadgetItem (0, -1, "Node "+Str(a), 0, 0)
    AddGadgetItem(0, -1, "Sub-Item 1", 0, 1)
    AddGadgetItem(0, -1, "Sub-Item 2", 0, 1)
    AddGadgetItem(0, -1, "Sub-Item 3", 0, 1)
    AddGadgetItem(0, -1, "Sub-Item 4", 0, 1)
    AddGadgetItem (0, -1, "File "+Str(a), 0, 0)
  Next
  count = CountGadgetItems(0)  
  AddWindowTimer(0,125,100) 
  Repeat
    Select WaitWindowEvent()
        
      Case #PB_Event_CloseWindow
        Quit = 1
        
      Case #PB_Event_Timer
        If GetActiveGadget() = 0 And run = 1          
          For item = 0 To count
            If GetGadgetItemState(0,item) & #PB_Tree_Expanded
              run = 0
              Debug item 
              Break
            EndIf
          Next 
        EndIf        
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 0
            If run = 0
              Debug GetGadgetState(0)
              If GetGadgetItemAttribute(0,GetGadgetState(0),#PB_Tree_SubLevel) <> 1
                ;SetGadgetItemState(0,item, #PB_Tree_Expanded)
                ;Else
                SetGadgetItemState(0,item, #PB_Tree_Collapsed)
              EndIf
              run =1
            EndIf 
        EndSelect
        
    EndSelect
  Until Quit = 1
EndIf
Edit :
- Fixed closing node after selecting item
- You must close the expanded node after selecting any item to behave as before
- Now you get any Node or item by clicking it(Node ID not available in PB commands)
Last edited by RASHAD on Sat Feb 27, 2021 12:41 pm, edited 1 time in total.
Egypt my love
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: TreeGadget collapse nodes

Post by mk-soft »

@RASHAD
Good idea, but when you select a subnode item, the node closes.

@All
Everything is not optimal.
MacOS does not return a gadget event when the TreeGadget expands or collapses. So the evaluation is done by default event.
Linux constantly fires default events with every change or query of the TreeGadget. So the evaluation is in the EventGadget.
Windows swallows events. So evaluate with BindEvent.

So you can see again how differently the OS work.
So many thanks to Fred, that at least the basic GUI events arrive at us with WaitWindowEvent for all OS.

Update v1.03.0
- Optimize
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: TreeGadget collapse nodes

Post by mk-soft »

Update v1.04.0
- macOS Notification
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: TreeGadget collapse nodes

Post by BarryG »

mk-soft, in your code, if the user double-clicks a node name (instead of the expand/collapse button next to it), then the other open nodes don't close.
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: TreeGadget collapse nodes

Post by mk-soft »

BarryG wrote: Sun Oct 10, 2021 10:54 am mk-soft, in your code, if the user double-clicks a node name (instead of the expand/collapse button next to it), then the other open nodes don't close.
Why should the other nodes close, it is OS specific normal that the other nodes remain open. Nothing is changed here.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: TreeGadget collapse nodes

Post by BarryG »

mk-soft wrote: Sun Oct 10, 2021 11:34 amWhy should the other nodes close, it is OS specific normal that the other nodes remain open. Nothing is changed here.
The whole point of this topic is to auto-close the others when one is open:
collectordave wrote: Thu Feb 25, 2021 4:45 pmI am trying to only have one node open at any one time.
So if you select Node 0 it expands then if you select Node 1 node 0 collapses and node 1 expands.
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: TreeGadget collapse nodes

Post by mk-soft »

You are right,

I look later for windows
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Post Reply