Skip to content

Commit 173c5c2

Browse files
committed
List window filter optimisation from sidestream.
beyond-all-reason/BYAR-Chobby@2368884
1 parent d9768c2 commit 173c5c2

1 file changed

Lines changed: 60 additions & 13 deletions

File tree

LuaMenu/widgets/chobby/components/list_window.lua

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,11 @@ function ListWindow:Clear()
119119
self.listPanel:ClearChildren()
120120
self.scrollChildren = 0
121121
self.itemNames = {}
122-
self.itemForceToColumFunc = {}
123-
self.itemPanelMapping = {}
124-
self.orderPanelMapping = {}
122+
self.itemPanelMapping = {} -- {id = panel{Index = placeinlist, id = id, inFilter = bool}}, maps
123+
self.orderPanelMapping = {} -- {index = panel{Index = placeinlist, id = id, inFilter = bool}}
125124
end
126125

127-
function ListWindow:AddRow(items, id, forceToColumnFunc)
126+
function ListWindow:AddRow(items, id)
128127
if self.itemPanelMapping[id] then
129128
--Spring.Log("Chobby", LOG.ERROR, "Tried to add duplicate list window item", id)
130129
return
@@ -137,7 +136,6 @@ function ListWindow:AddRow(items, id, forceToColumnFunc)
137136
end
138137

139138
self.itemNames[id] = itemNames
140-
self.itemForceToColumFunc[id] = forceToColumnFunc
141139

142140
local container = Control:New {
143141
name = "container",
@@ -158,7 +156,7 @@ function ListWindow:AddRow(items, id, forceToColumnFunc)
158156
}
159157

160158
local index = self.scrollChildren + 1
161-
local x,y,width,height = self:CalulatePosition(index)
159+
local x,y,width,height = self:CalculatePosition(index)
162160
local w = Control:New {
163161
x = x,
164162
width = width,
@@ -177,6 +175,7 @@ function ListWindow:AddRow(items, id, forceToColumnFunc)
177175
self.orderPanelMapping[index] = w
178176

179177
w.inFilter = self:ItemInFilter(id)
178+
w:SetVisibility(w.inFilter)
180179
self:RecalculateOrder(id)
181180
end
182181

@@ -190,7 +189,7 @@ function ListWindow:GetRowItems(id)
190189
return self.itemNames[id]
191190
end
192191

193-
function ListWindow:CalulatePosition(index)
192+
function ListWindow:CalculatePosition(index)
194193
local xAcross = ((index - 1)%self.columns)/self.columns
195194
local row = math.floor((index - 1)/self.columns)
196195

@@ -202,7 +201,7 @@ function ListWindow:CalulatePosition(index)
202201
end
203202

204203
function ListWindow:RecalculatePosition(index)
205-
local x, y, width, height = self:CalulatePosition(index)
204+
local x,y,width,height = self:CalculatePosition(index)
206205

207206
local child = self.orderPanelMapping[index]
208207

@@ -221,12 +220,61 @@ function ListWindow:ItemInFilter(id)
221220
return true
222221
end
223222

223+
function ListWindow:SetPosition(panel, index)
224+
local x,y, width, height = self:CalculatePosition(index)
225+
panel._relativeBounds.left = x
226+
panel._relativeBounds.width = width
227+
panel:SetPos(nil,y, nil, adjustFeatureHeight)
228+
panel:UpdateClientArea()
229+
end
230+
224231
function ListWindow:UpdateFilters()
225-
for i = 1, self.scrollChildren do
226-
self.orderPanelMapping[i].inFilter = self:ItemInFilter(self.orderPanelMapping[i].id)
232+
-- this updates all the elements
233+
-- should only be really called when filter parameters change,
234+
-- but is now fast enough to not really care about that
235+
-- dont even sort filtered out items
236+
-- filtered item positions are also set to the end of the list.
237+
238+
-- refresh filtered items
239+
local infilters = {} -- array of visible IDs
240+
local numinfilters = 0
241+
local invisible = {} -- array of invisible IDs
242+
local numinvisible = 0
243+
for index, panel in ipairs(self.orderPanelMapping) do
244+
local oldFilter = panel.inFilter
245+
panel.inFilter = self:ItemInFilter(panel.id)
246+
if panel.inFilter then
247+
numinfilters = numinfilters + 1
248+
infilters[numinfilters] = panel.id
249+
else
250+
numinvisible = numinvisible + 1
251+
invisible[numinvisible] = panel.id
252+
end
253+
254+
if oldFilter ~= panel.inFilter then -- only update on status change
255+
panel:SetVisibility(panel.inFilter)
256+
end
227257
end
228-
for id, _ in pairs(self.itemPanelMapping) do
229-
self:RecalculateOrder(id)
258+
259+
-- Create a localized lambda sort function and sort the visible ones
260+
local listWindow = self
261+
local lambda = function (id1, id2)
262+
return listWindow:CompareItems(id1,id2)
263+
end
264+
table.sort(infilters, lambda)
265+
266+
-- add the invisible ones to the end of the sorted list
267+
for i = 1, numinvisible do
268+
infilters[numinfilters+i] = invisible[i]
269+
end
270+
-- set the position of all of them one by one if it has changed
271+
for newindex, id in ipairs(infilters) do
272+
local panel = self.itemPanelMapping[id]
273+
if panel.index ~= newindex then
274+
self:SetPosition(panel, newindex)
275+
self.orderPanelMapping[newindex] = panel
276+
panel.index = newindex
277+
end
230278
end
231279
end
232280

@@ -305,6 +353,5 @@ function ListWindow:RemoveRow(id)
305353
self.listPanel:RemoveChild(panel)
306354
self.scrollChildren = self.scrollChildren - 1
307355
self.itemNames[id] = nil
308-
self.itemForceToColumFunc[id] = nil
309356
self.itemPanelMapping[id] = nil
310357
end

0 commit comments

Comments
 (0)