2 --Copyright (C) 2013 sapier
4 --This program is free software; you can redistribute it and/or modify
5 --it under the terms of the GNU Lesser General Public License as published by
6 --the Free Software Foundation; either version 2.1 of the License, or
7 --(at your option) any later version.
9 --This program is distributed in the hope that it will be useful,
10 --but WITHOUT ANY WARRANTY; without even the implied warranty of
11 --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 --GNU Lesser General Public License for more details.
14 --You should have received a copy of the GNU Lesser General Public License along
15 --with this program; if not, write to the Free Software Foundation, Inc.,
16 --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 --------------------------------------------------------------------------------
19 -- Generic implementation of a filter/sortable list --
21 -- Filterlist needs to be initialized on creation. To achieve this you need to --
22 -- pass following functions: --
23 -- raw_fct() (mandatory): --
24 -- function returning a table containing the elements to be filtered --
25 -- compare_fct(element1,element2) (mandatory): --
26 -- function returning true/false if element1 is same element as element2 --
27 -- uid_match_fct(element1,uid) (optional) --
28 -- function telling if uid is attached to element1 --
29 -- filter_fct(element,filtercriteria) (optional) --
30 -- function returning true/false if filtercriteria met to element --
31 -- fetch_param (optional) --
32 -- parameter passed to raw_fct to aquire correct raw data --
34 --------------------------------------------------------------------------------
37 --------------------------------------------------------------------------------
38 function filterlist.refresh(this)
39 this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
40 filterlist.process(this)
43 --------------------------------------------------------------------------------
44 function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
46 assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
47 assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
51 this.m_raw_list_fct = raw_fct
52 this.m_compare_fct = compare_fct
53 this.m_filter_fct = filter_fct
54 this.m_uid_match_fct = uid_match_fct
56 this.m_filtercriteria = nil
57 this.m_fetch_param = fetch_param
59 this.m_sortmode = "none"
62 this.m_processed_list = nil
63 this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
65 filterlist.process(this)
70 --------------------------------------------------------------------------------
71 function filterlist.add_sort_mechanism(this,name,fct)
72 this.m_sort_list[name] = fct
75 --------------------------------------------------------------------------------
76 function filterlist.set_filtercriteria(this,criteria)
77 if criteria == this.m_filtercriteria and
78 type(criteria) ~= "table" then
81 this.m_filtercriteria = criteria
82 filterlist.process(this)
85 --------------------------------------------------------------------------------
86 function filterlist.get_filtercriteria(this)
87 return this.m_filtercriteria
90 --------------------------------------------------------------------------------
91 --supported sort mode "alphabetic|none"
92 function filterlist.set_sortmode(this,mode)
93 if (mode == this.m_sortmode) then
96 this.m_sortmode = mode
97 filterlist.process(this)
100 --------------------------------------------------------------------------------
101 function filterlist.get_list(this)
102 return this.m_processed_list
105 --------------------------------------------------------------------------------
106 function filterlist.get_raw_list(this)
107 return this.m_raw_list
110 --------------------------------------------------------------------------------
111 function filterlist.get_raw_element(this,idx)
112 if type(idx) ~= "number" then
116 if idx ~= nil and idx > 0 and idx < #this.m_raw_list then
117 return this.m_raw_list[idx]
123 --------------------------------------------------------------------------------
124 function filterlist.get_raw_index(this,listindex)
125 assert(this.m_processed_list ~= nil)
127 if listindex ~= nil and listindex > 0 and
128 listindex <= #this.m_processed_list then
129 local entry = this.m_processed_list[listindex]
131 for i,v in ipairs(this.m_raw_list) do
133 if this.m_compare_fct(v,entry) then
142 --------------------------------------------------------------------------------
143 function filterlist.get_current_index(this,listindex)
144 assert(this.m_processed_list ~= nil)
146 if listindex ~= nil and listindex > 0 and
147 listindex <= #this.m_raw_list then
148 local entry = this.m_raw_list[listindex]
150 for i,v in ipairs(this.m_processed_list) do
152 if this.m_compare_fct(v,entry) then
161 --------------------------------------------------------------------------------
162 function filterlist.process(this)
163 assert(this.m_raw_list ~= nil)
165 if this.m_sortmode == "none" and
166 this.m_filtercriteria == nil then
167 this.m_processed_list = this.m_raw_list
171 this.m_processed_list = {}
173 for k,v in pairs(this.m_raw_list) do
174 if this.m_filtercriteria == nil or
175 this.m_filter_fct(v,this.m_filtercriteria) then
176 table.insert(this.m_processed_list,v)
180 if this.m_sortmode == "none" then
184 if this.m_sort_list[this.m_sortmode] ~= nil and
185 type(this.m_sort_list[this.m_sortmode]) == "function" then
187 this.m_sort_list[this.m_sortmode](this)
191 --------------------------------------------------------------------------------
192 function filterlist.size(this)
193 if this.m_processed_list == nil then
197 return #this.m_processed_list
200 --------------------------------------------------------------------------------
201 function filterlist.uid_exists_raw(this,uid)
202 for i,v in ipairs(this.m_raw_list) do
203 if this.m_uid_match_fct(v,uid) then
210 --------------------------------------------------------------------------------
211 function filterlist.raw_index_by_uid(this, uid)
212 local elementcount = 0
214 for i,v in ipairs(this.m_raw_list) do
215 if this.m_uid_match_fct(v,uid) then
216 elementcount = elementcount +1
222 -- If there are more elements than one with same name uid can't decide which
223 -- one is meant. This shouldn't be possible but just for sure.
224 if elementcount > 1 then
231 --------------------------------------------------------------------------------
232 -- COMMON helper functions --
233 --------------------------------------------------------------------------------
235 --------------------------------------------------------------------------------
236 function compare_worlds(world1,world2)
238 if world1.path ~= world2.path then
242 if world1.name ~= world2.name then
246 if world1.gameid ~= world2.gameid then
253 --------------------------------------------------------------------------------
254 function sort_worlds_alphabetic(this)
256 table.sort(this.m_processed_list, function(a, b)
257 --fixes issue #857 (crash due to sorting nil in worldlist)
258 if a == nil or b == nil then
259 if a == nil and b ~= nil then return false end
260 if b == nil and a ~= nil then return true end
263 if a.name:lower() == b.name:lower() then
264 return a.name < b.name
266 return a.name:lower() < b.name:lower()
270 --------------------------------------------------------------------------------
271 function sort_mod_list(this)
273 table.sort(this.m_processed_list, function(a, b)
274 -- Show game mods at bottom
275 if a.typ ~= b.typ then
276 return b.typ == "game_mod"
278 -- If in same or no modpack, sort by name
279 if a.modpack == b.modpack then
280 if a.name:lower() == b.name:lower() then
281 return a.name < b.name
283 return a.name:lower() < b.name:lower()
284 -- Else compare name to modpack name
286 -- Always show modpack pseudo-mod on top of modpack mod list
287 if a.name == b.modpack then
289 elseif b.name == a.modpack then
293 local name_a = a.modpack or a.name
294 local name_b = b.modpack or b.name
295 if name_a:lower() == name_b:lower() then
296 return name_a < name_b
298 return name_a:lower() < name_b:lower()