ListIconGadget GetSelectedItems (All OS)

Share your advanced PureBasic knowledge/code with the community.
User avatar
mk-soft
Always Here
Always Here
Posts: 6207
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

ListIconGadget GetSelectedItems (All OS)

Post by mk-soft »

After a query ...
Get selected items into an array.

Update v1.01.5
- Bugfix window check count
- Update example

Code: Select all

;-TOP

; Comment : GetSelectedItems (All OS)
; Author  : mk-soft
; Version : v1.01.5
; Date    : 29.08.2023
; Update  : 30.08.2023

; Link    : https://www.purebasic.fr/english/viewtopic.php?t=82334

EnableExplicit

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  
  ImportC ""
    gtk_tree_path_get_indices_with_depth(*path, depth)
  EndImport
  
  Structure udtItemsArray
    *pData.Integer
  EndStructure
  
  ProcedureC GFuncSelectedItemsCB(*data, *userdata.udtItemsArray)
    Protected *array.long, depth = 1
    *array = gtk_tree_path_get_indices_with_depth(*data, @depth)
    *userdata\pData\i = *array\l
    *userdata\pData + SizeOf(Integer)
  EndProcedure
  
CompilerEndIf

Procedure GetSelectedItems(Gadget, Array Items(1)) ; Result count of items
  
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_MacOS
      Protected IndexSet, cnt
      IndexSet = CocoaMessage(0, GadgetID(Gadget), "selectedRowIndexes")
      cnt = CocoaMessage(0, IndexSet, "count")
      If cnt > 0
        Dim Items(cnt - 1)
        CocoaMessage(0, IndexSet, "getIndexes:", @Items(), "maxCount:", cnt, "inIndexRange:", #nil)
      EndIf
      
    CompilerCase #PB_OS_Windows
      Protected hWnd, pos, cnt
      hWnd = GadgetID(Gadget)
      cnt = SendMessage_(hWnd, #LVM_GETSELECTEDCOUNT, 0, 0)
      If cnt > 0
        Dim Items(cnt - 1)
        cnt = 0
        pos = -1
        pos = SendMessage_(hWnd, #LVM_GETNEXTITEM, pos, #LVNI_SELECTED)
        While pos <> -1
          Items(cnt) = pos
          cnt + 1
          pos = SendMessage_(hWnd, #LVM_GETNEXTITEM, pos, #LVNI_SELECTED)
        Wend
      EndIf
      
    CompilerCase #PB_OS_Linux
      Protected *selection, *list, cnt, Items.udtItemsArray
      *selection = gtk_tree_view_get_selection_(GadgetID(Gadget))
      *list = gtk_tree_selection_get_selected_rows_(*selection, 0)
      cnt = g_list_length_(*list)
      If cnt > 0
        Dim Items(cnt - 1)
        Items\pData = @Items()
        g_list_foreach_(*list, @GFuncSelectedItemsCB(), @Items)
      EndIf
      g_list_free_(*list)
      
  CompilerEndSelect
  
  ProcedureReturn cnt
EndProcedure

; ****

CompilerIf #PB_Compiler_IsMainFile
  
  ;- Example
  
  #ProgramTitle = "Example - ListIconGadget GetSelectedItems"
  #ProgramVersion = "v1.01.5"
  
  Enumeration Windows
    #Main
  EndEnumeration
  
  Enumeration MenuBar
    #MainMenu
  EndEnumeration
  
  Enumeration MenuItems
    #MainMenuAbout
    #MainMenuExit
  EndEnumeration
  
  Enumeration Gadgets
    #MainList
    #MainButtonOk
    #MainButtonCancel
  EndEnumeration
  
  Enumeration StatusBar
    #MainStatusBar
  EndEnumeration
  
  ; ----
  
  Procedure FillList(Gadget)
    Protected txt.s, i, c
    RemoveGadgetColumn(Gadget, #PB_All)
    ; Add columns
    AddGadgetColumn(Gadget, 0, "Column 1", 200)
    AddGadgetColumn(Gadget, 1, "Column 2", 200)
    AddGadgetColumn(Gadget, 2, "Column 3", 200)
    AddGadgetColumn(Gadget, 3, "Column 4", 200)
    AddGadgetColumn(Gadget, 4, "Column 5", 200)
    AddGadgetColumn(Gadget, 5, "Column 6", 200)
    AddGadgetColumn(Gadget, 6, "Column 7", 200)
    AddGadgetColumn(Gadget, 7, "Column 8", 200)
    ; Add Items
    For i = 1 To 1000
      txt = ""
      For c = 1 To 8
        txt + "Item " + Str(i) + "." + Str(c) + #LF$
      Next
      AddGadgetItem(Gadget, -1, txt)
    Next  
  EndProcedure
  
  ; ----
  
  Procedure UpdateWindow()
    Protected dx, dy
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
    ; Resize gadgets
    ResizeGadget(#MainList, 5, 5, dx - 10, dy - 45)
    ResizeGadget(#MainButtonok, 10, dy - 35, 120, 30)
    ResizeGadget(#MainButtonCancel, dx - 130, dy - 35, 120, 30)
  EndProcedure
  
  ; ----
  
  Procedure Main()
    Protected dx, dy
    
    Protected cnt, idx
    Dim Items(0)
    
    #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
    
    If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, #ProgramTitle , #MainStyle)
      ; Menu
      CreateMenu(#MainMenu, WindowID(#Main))
      MenuTitle("&File")
      CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
        MenuItem(#PB_Menu_About, "")
      CompilerElse
        MenuItem(#MainMenuAbout, "About")
      CompilerEndIf
      ; Menu File Items
      
      CompilerIf Not #PB_Compiler_OS = #PB_OS_MacOS
        MenuBar()
        MenuItem(#MainMenuExit, "E&xit")
      CompilerEndIf
      
      ; StatusBar
      CreateStatusBar(#MainStatusBar, WindowID(#Main))
      AddStatusBarField(#PB_Ignore)
      
      ; Gadgets
      dx = WindowWidth(#Main)
      dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
      ListIconGadget(#MainList, 5, 5, dx -10, dy - 45, "", 0, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_FullRowSelect | #PB_ListIcon_MultiSelect)
      ButtonGadget(#MainButtonok, 10, dy - 35, 120, 30, "Ok")
      ButtonGadget(#MainButtonCancel, dx - 130, dy - 35, 120, 30, "Cancel")
      
      FillList(#MainList)
      
      ; Bind Events
      BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
      
      ; Event Loop
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_CloseWindow
            Select EventWindow()
              Case #Main
                Break
                
            EndSelect
            
          Case #PB_Event_Menu
            Select EventMenu()
                CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
                Case #PB_Menu_About
                  PostEvent(#PB_Event_Menu, #Main, #MainMenuAbout)
                  
                Case #PB_Menu_Preferences
                  
                Case #PB_Menu_Quit
                  PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                  
                CompilerEndIf
                
              Case #MainMenuAbout
                MessageRequester("About", #ProgramTitle + #LF$ + #ProgramVersion, #PB_MessageRequester_Info)
                
              Case #MainMenuExit
                PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                
            EndSelect
            
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #MainList
                Select EventType()
                  Case #PB_EventType_Change
                    ;
                    
                EndSelect
                
              Case #MainButtonOk
                cnt = GetSelectedItems(#MainList, Items())
                For idx = 0 To cnt - 1
                  Debug Items(idx)
                Next
                
              Case #MainButtonCancel
                ;
                
            EndSelect
            
        EndSelect
      ForEver
      
    EndIf
    
  EndProcedure : Main()
  
CompilerEndIf
Last edited by mk-soft on Wed Aug 30, 2023 2:50 pm, edited 4 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
pamen
Enthusiast
Enthusiast
Posts: 193
Joined: Sat Dec 31, 2022 12:24 pm
Location: Cyprus
Contact:

Re: ListIconGadget GetSelectedItems (All OS)

Post by pamen »

Excellent!
Thank you.
User avatar
jacdelad
Addict
Addict
Posts: 1993
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: ListIconGadget GetSelectedItems (All OS)

Post by jacdelad »

There's a SendMessage command in Windows, #LVM_GETSELECTEDCOUNT, which let's you dim the array to the correct size right from the beginning.
https://learn.microsoft.com/en-us/windo ... ectedcount
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
mk-soft
Always Here
Always Here
Posts: 6207
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: ListIconGadget GetSelectedItems (All OS)

Post by mk-soft »

Update v1.01.3
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
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: ListIconGadget GetSelectedItems (All OS)

Post by Shardik »

mk-soft's code doesn't check if no item is selected at all and crashes with no item selected on Windows in

Code: Select all

Dim Items(cnt - 1)
BarryG
Addict
Addict
Posts: 4128
Joined: Thu Apr 18, 2019 8:17 am

Re: ListIconGadget GetSelectedItems (All OS)

Post by BarryG »

Why are we not just For/Nexting the list and just checking the #PB_ListIcon_Selected flag for each item?
User avatar
mk-soft
Always Here
Always Here
Posts: 6207
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: ListIconGadget GetSelectedItems (All OS)

Post by mk-soft »

Shardik wrote: Wed Aug 30, 2023 7:32 am mk-soft's code doesn't check if no item is selected at all and crashes with no item selected on Windows in

Code: Select all

Dim Items(cnt - 1)
Ups ...
Had only inserted #LVM_GETSELECTEDCOUNT later and was not paying attention.

Update v1.01.5
- Bugfix window check count
- Update example

@BarryG
I haven't checked, but this should be faster for large amounts of data.
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