How to detect listicongadget column header click
How to detect listicongadget column header click
I dont find this thread anymore where discussed about that?
Karu
			
			
									
									
						Karu
Re: How to detect listicongadget column header click
www.purebasic.fr/english/viewtopic.php?p=25851
old topiy, code maybe needs to be adapted to new version of pb.
			
			
									
									old topiy, code maybe needs to be adapted to new version of pb.
Tranquil
						Re: How to detect listicongadget column header click
Re: How to detect listicongadget column header click
Hello,
Freak's code works fine with PB 5.21, but it is Windows specific.
For Linux or Macintosh, I tried to see how to use BindEvent, but I did not find yet how to detect the column. It is not urgent, but I would like to use it in future versions of my application for Linux or Mac.
Thanks if you have any idea.
Jean.
			
			
									
									Freak's code works fine with PB 5.21, but it is Windows specific.
For Linux or Macintosh, I tried to see how to use BindEvent, but I did not find yet how to detect the column. It is not urgent, but I would like to use it in future versions of my application for Linux or Mac.
Thanks if you have any idea.
Jean.
PureBasic 6.20 beta 2 (x64) | Windows 10 Pro x64 | Intel(R) Core(TM) i7-8700 CPU @ 3.20Ghz 16 GB RAM, SSD 500 GB, PC locally assembled.
Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
						Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
Re: How to detect listicongadget column header click
Please try the cross-platform code example below which detects the clicked header column and the clicked row. I have tested it successfully on these operating systems:CONVERT wrote:Freak's code works fine with PB 5.21, but it is Windows specific.
For Linux or Macintosh, I tried to see how to use BindEvent, but I did not find yet how to detect the column. It is not urgent, but I would like to use it in future versions of my application for Linux or Mac.
Thanks if you have any idea.
- Debian 7 x86 with Gnome 3
- Fedora 20 x86 with Gnome 3
- Kubuntu 13.10 x86 with KDE
- Linux Mint 16 x86 with Cinnamon
- Lubuntu 13.10 x86 with LXDE
- MacOS X 10.6.8 (Snow Leopard) with PB 5.21 x86 and x64 in ASCII and unicode mode
- MacOS X 10.9.2 (Mavericks)
- OpenSUSE 13.1 with KDE
- PCLinuxOS x86 with KDE
- PearOS 8 x86 with a heavily modified Gnome 3
- Ubuntu 10.04 LTS x86 with Gnome 2
- Ubuntu 12.04 LTS x64 with KDE
- Ubuntu 12.04 LTS x64 with Unity
- Ubuntu 12.04 LTS x64 with Enlightenment
- Windows XP SP3 x86
- Windows 7 SP1 x64
- Xubuntu 13.10 x86 with Xfce
Code: Select all
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
OpenWindow(0, 200, 100, 450, 150, "Detect left click on header cell")
ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20, "Name",
  110, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", 300)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit"+ #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit"+ #LF$ +
  "321 Logo Drive, Mouse House, Downtown")
SetGadgetCallback(0, 0)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0 And EventType() = #PB_EventType_LeftClick
        If EventData()
          Debug "Left click on header of column " + Str(EventData() - 1)
        Else
          Debug "Left click on row " + Str(GetGadgetState(0))
        EndIf
      EndIf
  EndSelect
ForEver
					Last edited by Shardik on Sun Mar 23, 2014 8:43 pm, edited 1 time in total.
									
			
									
						Re: How to detect listicongadget column header click
Whoaooh! Great!
It already works on W7 32. I'll integrate it in my application (provided for GNU L3), with your name, of course.
Thanks, Shardik.
Jean.
			
			
									
									It already works on W7 32. I'll integrate it in my application (provided for GNU L3), with your name, of course.
Thanks, Shardik.
Jean.
PureBasic 6.20 beta 2 (x64) | Windows 10 Pro x64 | Intel(R) Core(TM) i7-8700 CPU @ 3.20Ghz 16 GB RAM, SSD 500 GB, PC locally assembled.
Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
						Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
Re: several ListIconGadgets in a same window
Hello Shardik,
Your code works fine (Windows 7 Home 32), but not in case of several ListIcon Gadgets in a same window, with eventually several panels.
I added a second ListIconGadgets in your code to test.
(I also replaced
"DefaultListIconCallback = SetWindowLong_(GadgetID(0)," by
"DefaultListIconCallback = SetWindowLong_(GadgetID(ListIconID),"
in the Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
I hope I did not make a mistake).
The problem is: how to manage the SetGadgetCallback() before the Repeat /Select WaitWindowEvent()?
I tried to put the SetGadgetCallback() in the repeat loop with a test of the last used ListIconGadget, but I got a stack overflow.
The version 7 below does only the 2 SetGadgetCallback() (one for every ListIconGadget) before the repeat, but, of course, it gives the column header only on the last ListIconGadget.
May be I can solve this problem by replacing DefaultListIconCallback.I by a map M_DefaultListIconCallback.I (str(ListIconID.I)) and also others variables.
Also, the SetWindowLong_ as to be replaced by SetWindowLongPtr_ for 64 compatibility.
Well, for the moment, I use Freak's code (only for Window), and I'll see later for Linux etc.
			
			
									
									Your code works fine (Windows 7 Home 32), but not in case of several ListIcon Gadgets in a same window, with eventually several panels.
I added a second ListIconGadgets in your code to test.
(I also replaced
"DefaultListIconCallback = SetWindowLong_(GadgetID(0)," by
"DefaultListIconCallback = SetWindowLong_(GadgetID(ListIconID),"
in the Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
I hope I did not make a mistake).
The problem is: how to manage the SetGadgetCallback() before the Repeat /Select WaitWindowEvent()?
I tried to put the SetGadgetCallback() in the repeat loop with a test of the last used ListIconGadget, but I got a stack overflow.
The version 7 below does only the 2 SetGadgetCallback() (one for every ListIconGadget) before the repeat, but, of course, it gives the column header only on the last ListIconGadget.
May be I can solve this problem by replacing DefaultListIconCallback.I by a map M_DefaultListIconCallback.I (str(ListIconID.I)) and also others variables.
Also, the SetWindowLong_ as to be replaced by SetWindowLongPtr_ for 64 compatibility.
Well, for the moment, I use Freak's code (only for Window), and I'll see later for Linux etc.
Code: Select all
; VERSION 7
;How To detect listicongadget column header click
;by Shardik » Tue Mar 18, 2014 23:18
EnableExplicit
Define CallbackListIconID.I
Define CallbackWindowID.I
CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux ; ------------------------------------------------
    ProcedureC ColumnHeaderClickCallback(*Column, ClickedHeaderColumn.I)
      Shared CallbackListIconID.I
      Shared CallbackWindowID.I
      PostEvent(#PB_Event_Gadget, CallbackWindowID, CallbackListIconID,
        #PB_EventType_LeftClick, ClickedHeaderColumn + 1)
    EndProcedure
    Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
      Shared CallbackWindowID.I
      Shared CallbackListIconID.I
      Protected Column.I
      Protected ColumnCount.I
      Protected ColumnIndex.I
      Protected *ListStore.GtkListStore
      CallbackWindowID = WindowID
      CallbackListIconID = ListIconID
      gtk_tree_view_set_headers_clickable_(GadgetID(CallbackListIconID), #True)
      *ListStore = gtk_tree_view_get_model_(GadgetID(CallbackListIconID))
      ColumnCount = (*ListStore\n_columns - 3) / 3
      For ColumnIndex = 0 To ColumnCount - 1
        Column = gtk_tree_view_get_column_(GadgetID(CallbackListIconID),
          ColumnIndex)
        If Column
          g_signal_connect_data_(Column, "clicked",
            @ColumnHeaderClickCallback(), 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 CallbackListIconID.I
      Shared CallbackWindowID.I
      Protected ClickedHeaderColumn.I
      
      ClickedHeaderColumn = Val(PeekS(CocoaMessage(0,
        CocoaMessage(0, TableColumn, "identifier"),
        "UTF8String"), -1, #PB_UTF8))
      PostEvent(#PB_Event_Gadget, CallbackWindowID, CallbackListIconID,
        #PB_EventType_LeftClick, ClickedHeaderColumn + 1)
    EndProcedure
    
    Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
      Shared CallbackListIconID.I
      Shared CallbackWindowID.I
      
      Protected AppDelegate.I
      Protected DelegateClass.I
      Protected Selector.I = sel_registerName(ConvertToUTF8("tableView:didClickTableColumn:"))
      Protected Types.S = ConvertToUTF8("v@:@@")
      
      CallbackListIconID = ListIconID
      CallbackWindowID = WindowID
      AppDelegate = CocoaMessage(0,
        CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
      DelegateClass = CocoaMessage(0, AppDelegate, "class")
      class_addMethod(DelegateClass, Selector, @ColumnHeaderClickCallback(),
        Types)
      CocoaMessage(0, GadgetID(CallbackListIconID), "setDelegate:", AppDelegate)
    EndProcedure
  CompilerCase #PB_OS_Windows ; ----------------------------------------------
    Define DefaultListIconCallback.I
    Procedure ColumnHeaderClickCallback(WindowHandle.I, Msg.I, WParam.I,
      LParam.I)
      Shared DefaultListIconCallback.I
      Shared CallbackListIconID.I
      Shared CallbackWindowID.I
      Protected Result.I
      Protected *Header.HD_NOTIFY
      Result = CallWindowProc_(DefaultListIconCallback, WindowHandle, Msg,
        WParam, LParam)
      If Msg = #WM_NOTIFY
        *Header = LParam
        If *Header\hdr\code = #HDN_ITEMCLICK
          PostEvent(#PB_Event_Gadget, CallbackWindowID, CallbackListIconID,
            #PB_EventType_LeftClick, *Header\iItem + 1)
        EndIf
      EndIf
      ProcedureReturn Result
    EndProcedure
    Procedure SetGadgetCallback(WindowID.I, ListIconID.I)
      Shared DefaultListIconCallback.I
      Shared CallbackListIconID.I
      Shared CallbackWindowID.I
      CallbackListIconID = ListIconID
      CallbackWindowID = WindowID
      DefaultListIconCallback = SetWindowLong_(GadgetID(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"
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)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #list1_nb, #list2_nb
          If EventType() = #PB_EventType_LeftClick
            If EventData()
              Debug "Left click on header of column " + Str(EventData() - 1) + " gadget=" + Str(EventGadget())
            Else
              Debug "Left click on row " + Str(GetGadgetState(EventGadget())) + " gadget=" + Str(EventGadget())
            EndIf
          EndIf
      EndSelect
  EndSelect
ForEver
PureBasic 6.20 beta 2 (x64) | Windows 10 Pro x64 | Intel(R) Core(TM) i7-8700 CPU @ 3.20Ghz 16 GB RAM, SSD 500 GB, PC locally assembled.
Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
						Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
Re: How to detect listicongadget column header click
Jean,
thank you for testing my example code with 2 different ListIconGadgets, for reporting the error and notifing me that I should replace SetWindowLong_() by SetWindowLongPtr_(). Unfortunately I never tested with 2 ListIconGadgets and so didn't discover the error. The problem is that you need to keep track of the WindowID and ListIconID for each ListIcon callback defined. I therefore modified my code to use the new linked list CallbackEntry() which is declared as Shared in the ColumnHeaderClickCallback() and SetGadgetCallback() and contains the WindowID and ListIconID (and DefaultCallback address on Windows) for each entry.
I also corrected a small error in your code:You shouldn't use EventGadget() twice in succession because the second call may obtain a different result as the first one! Therefore you should assign the result of EventGadget() to a variable and work with this variable afterwards:
I have modified your code and tested it successfully on Windows 7 x64, Ubuntu 12.04 x64 with KDE and MacOS X 10.6.8 (Snow Leopard). On Linux I had to implement a trick because the old callback only received the clicked header column but didn't know the ListIconID and was not able to find the correct ListIcon callback. Therefore I logically ORed the clicked header column with the ListIconID shifted left by 16 bits so that the callback now also knows the ListIconID in which the header click occurred.
I will also implemented the above changes in my first example.
Thank you again, Jean.
			
			
									
									
						thank you for testing my example code with 2 different ListIconGadgets, for reporting the error and notifing me that I should replace SetWindowLong_() by SetWindowLongPtr_(). Unfortunately I never tested with 2 ListIconGadgets and so didn't discover the error. The problem is that you need to keep track of the WindowID and ListIconID for each ListIcon callback defined. I therefore modified my code to use the new linked list CallbackEntry() which is declared as Shared in the ColumnHeaderClickCallback() and SetGadgetCallback() and contains the WindowID and ListIconID (and DefaultCallback address on Windows) for each entry.
I also corrected a small error in your code:
Code: Select all
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #list1_nb, #list2_nb
          If EventType() = #PB_EventType_LeftClick
            If EventData()
              Debug "Left click on header of column " + Str(EventData() - 1) + " gadget=" + Str(EventGadget())Code: Select all
    Case #PB_Event_Gadget
      GadgetID = EventGadget()
      Select GadgetID
        Case #list1_nb, #list2_nb
          If EventType() = #PB_EventType_LeftClick
            If EventData()
              Debug "Left click on header of column " + Str(EventData() - 1) + " gadget=" + Str(GadgetID)
Code: Select all
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)
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
          If EventType() = #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
          EndIf
      EndSelect
  EndSelect
ForEverThank you again, Jean.
Re: How to detect listicongadget column header click
Thanks a lot to you, Shardik!!!
What's a very great job!
			
			
									
									What's a very great job!
PureBasic 6.20 beta 2 (x64) | Windows 10 Pro x64 | Intel(R) Core(TM) i7-8700 CPU @ 3.20Ghz 16 GB RAM, SSD 500 GB, PC locally assembled.
Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
						Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
Re: How to detect listicongadget column header click
There seems a bug in the Mac OS version. This code deactivates the #PB_EventType_Change event!! Take the code above and replace the last lines (see below). If you click (or select a new entry with arrow keys) in the left list, then no #PB_EventType_Change event is triggered. If you click (or select a new entry with arrow keys) in the right list, then a #PB_EventType_Change event is triggered:
			
			
									
									
						Code: Select all
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
ForEverRe: How to detect listicongadget column header click
I have posted a modified version for MacOS here which also generates #PB_EventType_Change events.Lebostein wrote:There seems a bug in the Mac OS version. This code deactivates the #PB_EventType_Change event!!
Re: How to detect listicongadget column header click
Thanks Shardik.
			
			
									
									PureBasic 6.20 beta 2 (x64) | Windows 10 Pro x64 | Intel(R) Core(TM) i7-8700 CPU @ 3.20Ghz 16 GB RAM, SSD 500 GB, PC locally assembled.
Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
						Come back to 6.11 LTS 64 bits because of an issue with #PB_ComboBox_UpperCase in ComboBoxGadget() (Oct. 10, 2024).
Re: How to detect listicongadget column header click
Can someone explain me why common needed functionality like this is (still) not included in the gadget library itself?
			
			
									
									
						
