Greetings,
I've had a search through the forum, but before I go down the rabbit hole, I wanted to post the question here.
In my application, which uses a ListIcon gadget to list, for example, computers, I'd like to apply a filter which would only display matching entries.
I'm thinking that alongside my ListIcon, I need a structured array to buffer what the ListIcon would display but with an additional dimension (called "Filtered"?) which would be true/false according to whether the array element gets copied to the ListIcon or not.
And the Filter gadget itself (an Edit) field, would have a delay if anything is entered, before traversing the array and updating the Filtered field, resulting in a row being (virtually) visible or hidden.
Thanks in advance for any help,
Amundo
Filter ListView/ListIcon contents
Filter ListView/ListIcon contents
Win10, PB6.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes
"When the facts change, I change my mind" - John Maynard Keynes
Re: Filter ListView/ListIcon contents
On Windows you can create 2 groups in the ListIconGadget. One group visible, one not. By moving the items between the groups, you can control visibility. If you use header less groups, it even won't look differently.
https://github.com/jacdelad/LIGEnhancements
https://github.com/jacdelad/LIGEnhancements
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
PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Re: Filter ListView/ListIcon contents
Thanks jacdelad, I'll take a lookjacdelad wrote: Tue Mar 11, 2025 7:24 am On Windows you can create 2 groups in the ListIconGadget. One group visible, one not. By moving the items between the groups, you can control visibility. If you use header less groups, it even won't look differently.
https://github.com/jacdelad/LIGEnhancements
Win10, PB6.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes
"When the facts change, I change my mind" - John Maynard Keynes
Re: Filter ListView/ListIcon contents
If I had to approach this problem, I would consider it as an interface to a database.
I would build a database with all the data (unfiltered). This can be done with SQL if the amount of data is large, or simply as a list of items (with NewList(), in PureBasic) if the number is small.
I would build a database with all the data (unfiltered). This can be done with SQL if the amount of data is large, or simply as a list of items (with NewList(), in PureBasic) if the number is small.
- The content presented in the ListIcon is then only an interface, that is, a sort of "window" allowing you to view part of the data based on the applied filter.
- Each time the filter is modified, a search is performed in the database and the result replaces what was previously in the ListIcon.
- You will probably need to maintain a reliable link between the database data and the displayed data. If there is a unique field that identifies each database item and this field is displayed in the ListIcon, this will be sufficient to establish the link. If not, you can assign a unique number to each item and store this number in the hidden part of the ListIcon, using SetGadgetItemData(). This way, when the user clicks on a row in the ListIcon, you can simply get the corresponding number with GetGadgetItemData() to find the corresponding item in your database.
Re: Filter ListView/ListIcon contents
It is much faster, at least ln windows, to switch between visible and invisible groups, than to fill/refill the ListView. This still applies when using SendMessage_(MyLIGID, #WM_SetRedraw, 0, 0).
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
PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Re: Filter ListView/ListIcon contents
Thanks Zapman, as I stated in my initial post, I went down the rabbit hole and used a List to buffer the data for the gadget (attached demo code shamelessly copied from Zapman's code and uses his Sortable ListIcon: https://www.purebasic.fr/english/viewtopic.php?t=86369)
By the way, the real application reads data from several Windows servers to display in the ListIcon. Being able to filter "on the fly" is a god-send when you're trying to quickly find one piece of information amongst potentially hundreds of rows. The demo only filters on the first column, but you get the idea...
By the way, the real application reads data from several Windows servers to display in the ListIcon. Being able to filter "on the fly" is a god-send when you're trying to quickly find one piece of information amongst potentially hundreds of rows. The demo only filters on the first column, but you get the idea...
Code: Select all
EnableExplicit
XIncludeFile "ColumnSortedListIconGadget.pbi"
Define Timer0
Define Filter0$
Define Event
Define FilterLen
Structure RowElement
Col0.s
Col1.s
Col2.s
Col3.s
Col4.s
Col5.s
Col6.s
Filtered.b ; Visible (0) Or Hidden (1)?
EndStructure
Global NewList ListIconData.RowElement() ; use a List as opposed to an Arry because all the sorting
; is handled by Zapman's code - thanks again, Zapman!
Procedure Resort(GagdetID)
Protected LastColumn, LastAscentDescent
LastColumn = GetLastSortingColumn(GagdetID)
LastAscentDescent = GetLastSortingAscentDescent(GagdetID)
SortListIcon(GagdetID, LastColumn, LastAscentDescent)
EndProcedure
Procedure ResetFilteredField()
ForEach ListIconData()
ListIconData()\Filtered = #False
Next
EndProcedure
Procedure FilterGadget(Col, Str$)
; Filter List field based on Col
Protected Field$
ForEach ListIconData()
Select Col
Case 0
Field$ = ListIconData()\Col0
Case 1
Field$ = ListIconData()\Col1
Case 2
Field$ = ListIconData()\Col2
Case 3
Field$ = ListIconData()\Col3
Case 4
Field$ = ListIconData()\Col4
Case 5
Field$ = ListIconData()\Col5
Case 6
Field$ = ListIconData()\Col6
EndSelect
If FindString(Field$, Str$, 1, #PB_String_NoCase)
ListIconData()\Filtered = #False
Else
ListIconData()\Filtered = #True
EndIf
Next
EndProcedure
Procedure UpdateListIcon(GagdetID)
; Populate ListIcon taking Filtered field into account
Protected Line$
ClearGadgetItems(GagdetID)
ForEach ListIconData()
If ListIconData()\Filtered
Continue
EndIf
Line$ = ListIconData()\Col0 + Chr(10)
Line$ + ListIconData()\Col1 + Chr(10)
Line$ + ListIconData()\Col2 + Chr(10)
Line$ + ListIconData()\Col3 + Chr(10)
Line$ + ListIconData()\Col4 + Chr(10)
Line$ + ListIconData()\Col5 + Chr(10)
Line$ + ListIconData()\Col6 + Chr(10)
AddGadgetItem(GagdetID, - 1, Line$)
Next
Resort(GagdetID)
EndProcedure
Define HWindow = OpenWindow(#PB_Any, 0, 0, 550, 320, "Sortable ListIconGadget demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
;
Global ListIconGagdet = ListIconGadget(#PB_Any, 0, 30, WindowWidth(HWindow), 225, "", 0, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
Define Filter0 = EditorGadget(#PB_Any, 0, 5, 70, 20)
;
AddGadgetColumn(ListIconGagdet, 0, "Alpha", 70)
SetGadgetItemAttribute(ListIconGagdet, 0, #PB_ListIcon_ColumnAlignment, #PB_ListIcon_Center, 0)
AddGadgetColumn(ListIconGagdet, 1, "Integer", 70)
AddGadgetColumn(ListIconGagdet, 2, "Decimal", 80)
AddGadgetColumn(ListIconGagdet, 3, "Hexa", 80)
AddGadgetColumn(ListIconGagdet, 4, "Dates", 80)
AddGadgetColumn(ListIconGagdet, 5, "Hours", 80)
AddGadgetColumn(ListIconGagdet, 6, "Sporty", 80)
SetGadgetItemAttribute(ListIconGagdet, 0, #PB_ListIcon_ColumnAlignment, #PB_ListIcon_Center, 6)
;
Define ct
For ct = 1 To 5
SetGadgetItemAttribute(ListIconGagdet, 0, #PB_ListIcon_ColumnAlignment, #PB_ListIcon_Right, ct)
Next
;
Define mDate.q = Date()
Define AlphaList$ = "élève,devant,front,Absent,Column,Final,tirant,global,$,"
Define HourList$ = "12:30:20,12:30:00,12:30,18:10,6:00 PM,11:00 AM,9:45:15,8:45,16h30mn,"
Define SportyTimeList$ = "30'',5'20'',1'14''80''',1'14,5'80''',20'',10'50'',4'40''30''',90'''"
For ct = 1 To 9
AddElement(ListIconData())
ListIconData()\Col0 = StringField(AlphaList$, ct, ",")
ListIconData()\Col1 = Str(Random($FFFF))
ListIconData()\Col2 = StrF(Random($FFFFFF)/10000, 3)
ListIconData()\Col3 = "$" + RSet(Hex(Random($7FFFFFFF)), 8, "0")
ListIconData()\Col4 = FormatDate(CSLI_DateFormat$, mDate)
mDate + 100000
ListIconData()\Col5 = StringField(HourList$, ct, ",")
ListIconData()\Col6 = StringField(SportyTimeList$, ct, ",")
ListIconData()\Filtered = 0 ; 0 = visible
Next
UpdateListIcon(ListIconGagdet) ; populate gadget from List data
;
Define NotSortableOption = OptionGadget(#PB_Any, 15, WindowHeight(HWindow) - 50, 140, 22, "Reset to not sortable")
Define DontShowArrowsOption = OptionGadget(#PB_Any, 190, WindowHeight(HWindow) - 50, 150, 22, "Sortable with no arrows")
Define ShowLeftArrowsOption = OptionGadget(#PB_Any, 375, WindowHeight(HWindow) - 50, 150, 22, "Sortable with left arrows")
Define ShowTopArrowsOption = OptionGadget(#PB_Any, 15, WindowHeight(HWindow) - 30, 400, 22, "Sortable with top arrows (when clicked) - (XP compatible)")
SetGadgetState(ShowLeftArrowsOption, 1)
:
;
MakeListIconSortable(ListIconGagdet, #CSLI_LeftArrows) ; <-- This is the only line you need to make the gadget sortable.
;
; But you can also decide to sort the gadget by default from one column content:
SortListIcon(ListIconGagdet, 0, #CSLI_Ascent)
;
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Timer
Select EventTimer()
Case Timer0
Debug "Timer0 triggered, time to apply Filter0"
RemoveWindowTimer(HWindow, Timer0)
Filter0$ = GetGadgetText(Filter0)
FilterGadget(0, Filter0$)
UpdateListIcon(ListIconGagdet)
EndSelect
EndIf
If Event = #PB_Event_Gadget
Select EventGadget()
Case Filter0
If EventType() = #PB_EventType_Change
Filter0$ = GetGadgetText(Filter0)
Debug "Filter0 changed!" + Filter0$
If Len(Filter0$) = 0
; filter field cleared, reset Filtered field(s) to all be visible
ResetFilteredField()
UpdateListIcon(ListIconGagdet)
RemoveWindowTimer(HWindow, Timer0)
Else
RemoveWindowTimer(HWindow, Timer0) ; reset timer
AddWindowTimer(HWindow, Timer0, 1000)
EndIf
EndIf
Case NotSortableOption
MakeListIconSortable(ListIconGagdet, #CSLI_NotSortable)
Case DontShowArrowsOption
MakeListIconSortable(ListIconGagdet, #CSLI_NoArrow)
Case ShowLeftArrowsOption
MakeListIconSortable(ListIconGagdet, #CSLI_LeftArrows)
Case ShowTopArrowsOption
MakeListIconSortable(ListIconGagdet, #CSLI_TopArrows)
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
Win10, PB6.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes
"When the facts change, I change my mind" - John Maynard Keynes
Re: Filter ListView/ListIcon contents
Good point, Amundo, it works perfectly for me. The timer setting seems perfect.
Did you achieve exactly what you wanted?
Did you achieve exactly what you wanted?
Re: Filter ListView/ListIcon contents
Hi Zapman,
I'm (mostly) back from solving a long real-life issue, but yes, it seems to work great - just a few bugs to iron out (famous last words, right?).
Thanks again for all your help and sharing.
(Actually, the next major task is to populate the ListIcon from a thread...wish me luck!)
I'm (mostly) back from solving a long real-life issue, but yes, it seems to work great - just a few bugs to iron out (famous last words, right?).
Thanks again for all your help and sharing.
(Actually, the next major task is to populate the ListIcon from a thread...wish me luck!)
Win10, PB6.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes
"When the facts change, I change my mind" - John Maynard Keynes
Re: Filter ListView/ListIcon contents
As long as it is Windows, you can also fill the ListIconGadget from a thread.
But be sure to activate the ThreadSafe compiler option.
Under Linux and macOS you have to pass the data to the MainScope with PostEvent.
To do this, search for: ‘Mini Thread Control’
But be sure to activate the ThreadSafe compiler option.
Under Linux and macOS you have to pass the data to the MainScope with PostEvent.
To do this, search for: ‘Mini Thread Control’
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
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Filter ListView/ListIcon contents
Hello,
For filtering rows in a LIG, you can also see this post by nicolaus and the adaptation made by flype.
Note : Some constants are now native in PB and must be commented
For filtering rows in a LIG, you can also see this post by nicolaus and the adaptation made by flype.
Note : Some constants are now native in PB and must be commented

If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Except on this sentence...