It is currently Mon Jan 27, 2020 9:30 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: ListIconGadget: No #PB_EventType_Change!
PostPosted: Tue Jun 07, 2016 8:11 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
If you change the selected row in a ListIconGadget with the arrow keys, no #PB_EventType_Change Event is triggered! No chance to find out if the selection inside the ListIconGadget was changed....

This is Mac OS only. With Windows it works.


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Sun Jun 26, 2016 6:27 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
It seems the bug is active only, if a GadgetCallback is activated:
viewtopic.php?p=490253#p490253


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Sun Jun 26, 2016 8:55 am 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 13707
Location: France
Could you post a full working snippet please ?


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Mon Jun 27, 2016 11:49 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
Left gadget (with a callback) don't send a #PB_EventType_Change if you select a new row with up/down arrow keys:

Code:
EnableExplicit

Structure CallbackEntry
  WindowID.I
  ListIconID.I
  DefaultCallback.I
EndStructure

NewList CallbackEntry.CallbackEntry()

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux ; ------------------------------------------------
    ProcedureC ColumnHeaderClickCallback(*Column, ListIconData.I)
      Shared CallbackEntry()

      ForEach CallbackEntry()
        If ListIconData >> 16 = CallbackEntry()\ListIconID
          Break
        EndIf
      Next

      PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID,
        CallbackEntry()\ListIconID, #PB_EventType_LeftClick,
        (ListIconData & $FFFF) + 1)
    EndProcedure

    Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
      Shared CallbackEntry()

      Protected Column.I
      Protected ColumnCount.I
      Protected ColumnIndex.I
      Protected *ListStore.GtkListStore

      AddElement(CallbackEntry())
      CallbackEntry()\WindowID = WindowID
      CallbackEntry()\ListIconID = ListIconID
      gtk_tree_view_set_headers_clickable_(GadgetID(ListIconID), #True)
      *ListStore = gtk_tree_view_get_model_(GadgetID(ListIconID))
      ColumnCount = (*ListStore\n_columns - 3) / 3

      For ColumnIndex = 0 To ColumnCount - 1
        Column = gtk_tree_view_get_column_(GadgetID(CallbackEntry()\ListIconID),
          ColumnIndex)

        If Column
          g_signal_connect_data_(Column, "clicked",
            @ColumnHeaderClickCallback(), ListIconID << 16 | ColumnIndex, 0, 0)
        EndIf
      Next ColumnIndex
    EndProcedure
  CompilerCase #PB_OS_MacOS ; ------------------------------------------------
    ImportC ""
      sel_registerName(MethodName.S)
      class_addMethod(Class.I, Selector.I, Implementation.I, Types.S)
    EndImport

    Procedure.S ConvertToUTF8(String.S)
      Protected UTF8String.S = Space(StringByteLength(String))
      PokeS(@UTF8String, String, -1, #PB_UTF8)
      ProcedureReturn UTF8String
    EndProcedure
   
    ProcedureC ColumnHeaderClickCallback(Object.I, Selector.I, TableView.I,
      TableColumn.I)
      Shared CallbackEntry()

      Protected ClickedHeaderColumn.I
 
      ForEach CallbackEntry()
        If TableView = GadgetID(CallbackEntry()\ListIconID)
          Break
        EndIf
      Next
   
      ClickedHeaderColumn = Val(PeekS(CocoaMessage(0,
        CocoaMessage(0, TableColumn, "identifier"),
        "UTF8String"), -1, #PB_UTF8))
      PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID,
        CallbackEntry()\ListIconID, #PB_EventType_LeftClick,
        ClickedHeaderColumn + 1)
    EndProcedure
   
    Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
      Shared CallbackEntry()
     
      Protected AppDelegate.I
      Protected DelegateClass.I
      Protected Selector.I = sel_registerName(ConvertToUTF8("tableView:didClickTableColumn:"))
      Protected Types.S = ConvertToUTF8("v@:@@")

      AddElement(CallbackEntry())
      CallbackEntry()\WindowID = WindowID
      CallbackEntry()\ListIconID = ListIconID
      AppDelegate = CocoaMessage(0,
        CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
      DelegateClass = CocoaMessage(0, AppDelegate, "class")
      class_addMethod(DelegateClass, Selector, @ColumnHeaderClickCallback(),
        Types)
      CocoaMessage(0, GadgetID(CallbackEntry()\ListIconID),
        "setDelegate:", AppDelegate)
    EndProcedure
  CompilerCase #PB_OS_Windows ; ----------------------------------------------
    Procedure ColumnHeaderClickCallback(WindowHandle.I, Msg.I, WParam.I,
      LParam.I)
      Shared CallbackEntry()

      Protected Result.I
      Protected *Header.HD_NOTIFY

      ForEach CallbackEntry()
        If WindowHandle = GadgetID(CallbackEntry()\ListIconID)
          Break
        EndIf
      Next

      Result = CallWindowProc_(CallbackEntry()\DefaultCallback, WindowHandle,
        Msg, WParam, LParam)

      If Msg = #WM_NOTIFY
        *Header = LParam

        If *Header\hdr\code = #HDN_ITEMCLICK
          PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID,
            CallbackEntry()\ListIconID, #PB_EventType_LeftClick,
            *Header\iItem + 1)
        EndIf
      EndIf

      ProcedureReturn Result
    EndProcedure

    Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
      Shared CallbackEntry()

      AddElement(CallbackEntry())
      CallbackEntry()\WindowID = WindowID
      CallbackEntry()\ListIconID = ListIconID
      CallbackEntry()\DefaultCallback = SetWindowLongPtr_(GadgetID(CallbackEntry()\ListIconID),
        #GWL_WNDPROC, @ColumnHeaderClickCallback())
    EndProcedure ; -----------------------------------------------------------
CompilerEndSelect

; ========================================== SPECIFIC CODE FOR TESTING

Enumeration
  #zero
  #windows_nb
  #list1_nb
  #list2_nb
EndEnumeration

#Title_column1$ = "Name"
#Title_column2$ = "Address"

Define GadgetID.I

OpenWindow(#windows_nb, 0, 0, 950, 150, "Detect left click on header cell",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ListIconGadget(#list1_nb, 10, 10, 430, WindowHeight(#windows_nb) - 20, #Title_column1$,
  110, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#list1_nb, 1, #Title_column2$, 300)
AddGadgetItem(#list1_nb, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(#list1_nb, -1, "Ginger Brokeit"+ #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(#list1_nb, -1, "Didi Foundit"+ #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

ListIconGadget(#list2_nb, 460, 10, 430, WindowHeight(#windows_nb) - 20, #Title_column1$,
  110, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#list2_nb, 1, #Title_column2$, 300)
AddGadgetItem(#list2_nb, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(#list2_nb, -1, "Ginger Brokeit"+ #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(#list2_nb, -1, "Didi Foundit"+ #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

SetGadgetCallback(#windows_nb, #list1_nb)
;SetGadgetCallback(#windows_nb, #list2_nb) ; -> gadget 2 without that callback

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        ForEach CallbackEntry()
          SetWindowLongPtr_(GadgetID(CallbackEntry()\ListIconID),
            #GWL_WNDPROC, CallbackEntry()\DefaultCallback)
        Next
      CompilerEndIf

      Break
    Case #PB_Event_Gadget
      GadgetID = EventGadget()

      Select GadgetID
        Case #list1_nb, #list2_nb
          Select EventType()
          Case #PB_EventType_LeftClick
            If EventData()
              Debug "Left click on header of column " + Str(EventData() - 1) + " gadget=" + Str(GadgetID)
            Else
              Debug "Left click on row " + Str(GetGadgetState(GadgetID)) + " gadget=" + Str(GadgetID)
            EndIf
          Case #PB_EventType_Change
            Debug "changed"
          EndSelect
      EndSelect
  EndSelect
ForEver


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Thu Jul 07, 2016 8:19 am 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 13707
Location: France
You are replacing the delegate, so PB one isn't called anymore. It's not a PB bug.


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Wed Jul 13, 2016 9:59 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
Fred wrote:
You are replacing the delegate, so PB one isn't called anymore. It's not a PB bug.

I don't know what you mean. I copied this code from the forum.
Is it possible to catch a click on the List Icon Gadget header without "replacing the delegate"?


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Wed Jul 20, 2016 8:01 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
Can you add this "header click" official to PureBasic? Then we don't need to "replace the delegate".
That would be great.


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Sun Aug 07, 2016 8:09 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1678
Location: Germany
I have taken Lebostein's example, stripped off all specific Linux and Windows code for a clearer outline (so now it's only runnable on MacOS) and implemented a second callback for the method tableViewSelectionDidChange: to catch and signal all selection changes in both of the two ListIconGadgets.

I have tested the example successfully on MacOS 10.6.8 (Snow Leopard) and MacOS 10.11.6 (El Capitan) with PB 5.43 x86 and x64 (ASCII and Unicode mode) and with PB 5.50 x86 and x64.
Code:
EnableExplicit

ImportC ""
  sel_registerName(MethodName.P-ASCII)
  class_addMethod(Class.I, Selector.I, Implementation.I, Types.P-ASCII)
EndImport

Structure CallbackEntry
  WindowID.I
  ListIconID.I
  DefaultCallback.I
EndStructure

Define AppDelegate.I = CocoaMessage(0,
  CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Define DelegateClass.I = CocoaMessage(0, AppDelegate, "class")
Define NotificationCenter.I = CocoaMessage(0, 0,
  "NSNotificationCenter defaultCenter")

NewList CallbackEntry.CallbackEntry()

ProcedureC ColumnHeaderClickCallback(Object.I, Selector.I, TableView.I,
  TableColumn.I)
  Shared CallbackEntry()
 
  Protected ClickedHeaderColumn.I
 
  ForEach CallbackEntry()
    If TableView = GadgetID(CallbackEntry()\ListIconID)
      Break
    EndIf
  Next
 
  ClickedHeaderColumn = Val(PeekS(CocoaMessage(0,
    CocoaMessage(0, TableColumn, "identifier"),
    "UTF8String"), -1, #PB_UTF8))
  PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID,
    CallbackEntry()\ListIconID, #PB_EventType_LeftClick,
    ClickedHeaderColumn + 1)
EndProcedure

ProcedureC SelectionDidChangeCallback(Object.I, Selector.I, Notification.I)
  Shared CallbackEntry()
  Static ChangeSignalled.I

  If ChangeSignalled
    PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID,
      CallbackEntry()\ListIconID, #PB_EventType_Change)
    ChangeSignalled = #False
  Else
    ChangeSignalled = #True
  EndIf
EndProcedure

Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
  Shared AppDelegate.I
  Shared CallbackEntry()
  Shared DelegateClass.I
  Shared NotificationCenter.I
 
  AddElement(CallbackEntry())
  CallbackEntry()\WindowID = WindowID
  CallbackEntry()\ListIconID = ListIconID

  ; ----- Initialize callback for changing selection

  class_addMethod(DelegateClass,
    sel_registerName("tableViewSelectionDidChange:"),
    @SelectionDidChangeCallback(), "v@:@")
  CocoaMessage(0, NotificationCenter,
    "addObserver:", AppDelegate,
    "selector:", sel_registerName("tableViewSelectionDidChange:"),
    "name:$", @"NSTableViewSelectionDidChangeNotification",
    "object:", GadgetID(CallbackEntry()\ListIconID))

  ; ----- Initialize callback for header click

  class_addMethod(DelegateClass,
    sel_registerName("tableView:didClickTableColumn:"),
    @ColumnHeaderClickCallback(), "v@:@@")

  CocoaMessage(0, GadgetID(CallbackEntry()\ListIconID),
    "setDelegate:", AppDelegate)
EndProcedure

; ========================================== SPECIFIC CODE FOR TESTING

Enumeration
  #zero
  #windows_nb
  #list1_nb
  #list2_nb
EndEnumeration

#Title_column1$ = "Name"
#Title_column2$ = "Address"

Define GadgetID.I

OpenWindow(#windows_nb, 0, 0, 870, 110, "Detect left click on header cell",
  #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ListIconGadget(#list1_nb, 10, 10, 420, WindowHeight(#windows_nb) - 20,
  #Title_column1$, 110, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#list1_nb, 1, #Title_column2$, 300)
AddGadgetItem(#list1_nb, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(#list1_nb, -1, "Ginger Brokeit"+ #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(#list1_nb, -1, "Didi Foundit"+ #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

ListIconGadget(#list2_nb, 440, 10, 420, WindowHeight(#windows_nb) - 20,
  #Title_column1$, 110, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#list2_nb, 1, #Title_column2$, 300)
AddGadgetItem(#list2_nb, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(#list2_nb, -1, "Ginger Brokeit"+ #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(#list2_nb, -1, "Didi Foundit"+ #LF$ +
  "321 Logo Drive, Mouse House, Downtown")

SetGadgetCallback(#windows_nb, #list1_nb)
SetGadgetCallback(#windows_nb, #list2_nb)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      GadgetID = EventGadget()

      Select GadgetID
        Case #list1_nb, #list2_nb
          Select EventType()
          Case #PB_EventType_LeftClick
            If EventData()
              Debug "Left click on header of column " + Str(EventData() - 1) +
                ", Gadget " + Str(GadgetID)
            Else
              Debug "-> Left click on row " + Str(GetGadgetState(GadgetID)) +
                ", Gadget " + Str(GadgetID)
            EndIf
          Case #PB_EventType_Change
            Debug "Selected row changed:"
          EndSelect
      EndSelect
  EndSelect
ForEver

CocoaMessage(0, NotificationCenter, "removeObserver:", AppDelegate)


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Tue Sep 13, 2016 12:55 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
Thanks!!!! That's it! :D


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Tue Sep 13, 2016 2:17 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
I hope Fred will add the header click event to PB one day. In my eyes an essential thing for list table gadgets...


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Mon Jan 13, 2020 10:57 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
But #PB_EventType_Change returns the wrong GadgetID !!!!

add the gadget ID to the output:
Code:
Debug "Selected row changed, Gadget " + Str(GadgetID)

Start the code and click on the entries on left and right. The GadgetID is everytime = 3, whether you click left or right.
But if you click one time the header, then it suddenly works....


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Tue Jan 14, 2020 9:15 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1678
Location: Germany
Lebostein wrote:
But #PB_EventType_Change returns the wrong GadgetID !!!!

add the gadget ID to the output:
Code:
Debug "Selected row changed, Gadget " + Str(GadgetID)

Start the code and click on the entries on left and right. The GadgetID is everytime = 3, whether you click left or right.
But if you click one time the header, then it suddenly works....

You are right, it's a bug. The callback SelectionDidChangeCallback() is a notification callback which doesn't receive in its parameters the currently selected ListIconGadget (TableView) and column object (Table Column) like the ColumnHeaderClickCallback(). So in SelectionDidChangeCallback() PostEvent() incorrectly sends the previously selected linked list elements WindowID and ListIconID.

To eleminate this bug please change in SelectionDidChangeCallback() this code
Code:
    PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID,
      CallbackEntry()\ListIconID, #PB_EventType_Change)
against this modified one
Code:
    PostEvent(#PB_Event_Gadget, GetActiveWindow(), GetActiveGadget(),
      #PB_EventType_Change)

I have tested the modified example successfully on MacOS 10.14.6 'Mojave' with PB 5.71 x64.


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Wed Jan 15, 2020 11:17 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
Thats it!! :D Thanks a million!


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Fri Jan 17, 2020 2:23 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Jun 11, 2004 7:07 am
Posts: 615
Edit: It seems the last change influences other gadgets with the #PB_EventType_Change event. What about that solution? It seems it works, but I don't know if it's right:

Code:
ProcedureC SelectionDidChangeCallback(Object.I, Selector.I, Notification.I)
  Shared CallbackEntry()
  Static ChangeSignalled.I

  ForEach CallbackEntry()
    If GetActiveWindow() = CallbackEntry()\WindowID And GetActiveGadget() = CallbackEntry()\ListIconID
      If ChangeSignalled
        PostEvent(#PB_Event_Gadget, CallbackEntry()\WindowID, CallbackEntry()\ListIconID, #PB_EventType_Change)
        ChangeSignalled = #False
      Else
        ChangeSignalled = #True
      EndIf
    EndIf
  Next

EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: ListIconGadget: No #PB_EventType_Change!
PostPosted: Sun Jan 19, 2020 10:35 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 1678
Location: Germany
Lebostein wrote:
Edit: It seems the last change influences other gadgets with the #PB_EventType_Change event. What about that solution? It seems it works, but I don't know if it's right:

Your solution should be even better than my proposition. Your solution takes care that the correct entry in the shared LinkedList CallbackEntry() is selected. Due to the sharing of the LinkedList CallbackEntry() in the callbacks, the change of an entry in a callback is also in effect in the main program.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye