TreeGadget and #PB_EventType_Change

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

TreeGadget and #PB_EventType_Change

Post by srod »

Hi,

PB 5.60x86 (Windows 7).

I just about decided against posting this as a bug report, because some might argue that the way things are with the TreeGadget under Windows is fine and I almost agree! :)

The problem is that the event #PB_EventType_Change fires twice when you click a checkbox in a tree gadget. I am assuming that the first is a kind of 'deselection' event for the originally selected item as GetGadgetState() returns the old item in this case. Could be a bug though! :wink:

This 'problem' is highlighted with the following code :

Code: Select all

Declare OnChangeEvent()

If OpenWindow(0, 0, 0, 355, 180, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TreeGadget(0, 10, 10, 160, 160, #PB_Tree_CheckBoxes)
    AddGadgetItem (0, -1, "Node 1", 0, 0)        ; ImageID(x) as 4th parameter
    AddGadgetItem(0, -1, "Sub-Item 1", 0, 1)    ; These are on the 1st sublevel
    SetGadgetItemState(0, 0, #PB_Tree_Expanded)
    BindGadgetEvent(0, @OnChangeEvent(), #PB_EventType_Change)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Procedure OnChangeEvent()
  Protected i, state, item
  item = GetGadgetState(0)
  ;In the case that the main node's checkbox has been changed, we run through all child items and change their checkbox accordingly.
  If item = 0
    If GetGadgetItemState(0, 0) & #PB_Tree_Checked
      ;Check all child items.
        state = GetGadgetItemState(0, 1) | #PB_Tree_Checked
        SetGadgetItemState(0, 1, state)
    Else
      ;Uncheck all child items.
        state = GetGadgetItemState(0, 1) &~ #PB_Tree_Checked
        SetGadgetItemState(0, 1, state)
    EndIf
  EndIf
EndProcedure
With this code, check and uncheck the two checkboxes at will. However, if you check item 0's checkbox then the code will automatically check item 1's checkbox. Similar for unchecking item 0.

The problem is the code doesn't work properly!

After checking or unchecking item 0, try clicking item 1's checkbox directly and you will find that nothing happens. You will have to click a second time!

Seems a bug at first, but, well, it can be argued that I am abusing the event system here.

The problem is the aforementioned double firing of the #PB_EventType_Change event when clicking into checkboxes. Incidentally, I cannot use the #PB_EventType_LeftClick event as this does not record the setting of a checkbox by hitting the spacebar.

Basically, what is happening with the above code is if I have item 0 selected and then click the checkbox in item 1, then PB first changes the checkbox state in item 1 as required, the #PB_EventType_Change event then fires for deselecting item 0 (and my code automatically clears the checkbox in item 1) and then #PB_EventType_Change fires for item 1. Thus, from our point of view, nothing seems to happen after our first click.

As I say workarounds are simple enough, but I wonder as to the merit of #PB_EventType_Change firing twice for a single click into a checkbox. At best this is inconsistent because we do not generally get two such events when selecting tree items. If one event was to notify a checkbox change and the other to notify a new item selected then both should return the new item in GetGadgetState() which currently they do not.

Feature request then. :) Either remove this first invokation of #PB_EventType_Change (as Windows does not natively make two such notifications) or have both invokations ensure that GetGadgetState() returns the newly selected item.

Thanks.
I may look like a mule, but I'm not a complete ass.