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 -- TODO improve doc --
20 -- TODO code cleanup --
21 -- Generic implementation of a filter/sortable list --
23 -- Filterlist needs to be initialized on creation. To achieve this you need to --
24 -- pass following functions: --
25 -- raw_fct() (mandatory): --
26 -- function returning a table containing the elements to be filtered --
27 -- compare_fct(element1,element2) (mandatory): --
28 -- function returning true/false if element1 is same element as element2 --
29 -- uid_match_fct(element1,uid) (optional) --
30 -- function telling if uid is attached to element1 --
31 -- filter_fct(element,filtercriteria) (optional) --
32 -- function returning true/false if filtercriteria met to element --
33 -- fetch_param (optional) --
34 -- parameter passed to raw_fct to aquire correct raw data --
36 --------------------------------------------------------------------------------
39 --------------------------------------------------------------------------------
40 function filterlist.refresh(self)
41 self.m_raw_list = self.m_raw_list_fct(self.m_fetch_param)
42 filterlist.process(self)
45 --------------------------------------------------------------------------------
46 function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
48 assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
49 assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
53 self.m_raw_list_fct = raw_fct
54 self.m_compare_fct = compare_fct
55 self.m_filter_fct = filter_fct
56 self.m_uid_match_fct = uid_match_fct
58 self.m_filtercriteria = nil
59 self.m_fetch_param = fetch_param
61 self.m_sortmode = "none"
64 self.m_processed_list = nil
65 self.m_raw_list = self.m_raw_list_fct(self.m_fetch_param)
67 self.add_sort_mechanism = filterlist.add_sort_mechanism
68 self.set_filtercriteria = filterlist.set_filtercriteria
69 self.get_filtercriteria = filterlist.get_filtercriteria
70 self.set_sortmode = filterlist.set_sortmode
71 self.get_list = filterlist.get_list
72 self.get_raw_list = filterlist.get_raw_list
73 self.get_raw_element = filterlist.get_raw_element
74 self.get_raw_index = filterlist.get_raw_index
75 self.get_current_index = filterlist.get_current_index
76 self.size = filterlist.size
77 self.uid_exists_raw = filterlist.uid_exists_raw
78 self.raw_index_by_uid = filterlist.raw_index_by_uid
79 self.refresh = filterlist.refresh
81 filterlist.process(self)
86 --------------------------------------------------------------------------------
87 function filterlist.add_sort_mechanism(self,name,fct)
88 self.m_sort_list[name] = fct
91 --------------------------------------------------------------------------------
92 function filterlist.set_filtercriteria(self,criteria)
93 if criteria == self.m_filtercriteria and
94 type(criteria) ~= "table" then
97 self.m_filtercriteria = criteria
98 filterlist.process(self)
101 --------------------------------------------------------------------------------
102 function filterlist.get_filtercriteria(self)
103 return self.m_filtercriteria
106 --------------------------------------------------------------------------------
107 --supported sort mode "alphabetic|none"
108 function filterlist.set_sortmode(self,mode)
109 if (mode == self.m_sortmode) then
112 self.m_sortmode = mode
113 filterlist.process(self)
116 --------------------------------------------------------------------------------
117 function filterlist.get_list(self)
118 return self.m_processed_list
121 --------------------------------------------------------------------------------
122 function filterlist.get_raw_list(self)
123 return self.m_raw_list
126 --------------------------------------------------------------------------------
127 function filterlist.get_raw_element(self,idx)
128 if type(idx) ~= "number" then
132 if idx ~= nil and idx > 0 and idx <= #self.m_raw_list then
133 return self.m_raw_list[idx]
139 --------------------------------------------------------------------------------
140 function filterlist.get_raw_index(self,listindex)
141 assert(self.m_processed_list ~= nil)
143 if listindex ~= nil and listindex > 0 and
144 listindex <= #self.m_processed_list then
145 local entry = self.m_processed_list[listindex]
147 for i,v in ipairs(self.m_raw_list) do
149 if self.m_compare_fct(v,entry) then
158 --------------------------------------------------------------------------------
159 function filterlist.get_current_index(self,listindex)
160 assert(self.m_processed_list ~= nil)
162 if listindex ~= nil and listindex > 0 and
163 listindex <= #self.m_raw_list then
164 local entry = self.m_raw_list[listindex]
166 for i,v in ipairs(self.m_processed_list) do
168 if self.m_compare_fct(v,entry) then
177 --------------------------------------------------------------------------------
178 function filterlist.process(self)
179 assert(self.m_raw_list ~= nil)
181 if self.m_sortmode == "none" and
182 self.m_filtercriteria == nil then
183 self.m_processed_list = self.m_raw_list
187 self.m_processed_list = {}
189 for k,v in pairs(self.m_raw_list) do
190 if self.m_filtercriteria == nil or
191 self.m_filter_fct(v,self.m_filtercriteria) then
192 self.m_processed_list[#self.m_processed_list + 1] = v
196 if self.m_sortmode == "none" then
200 if self.m_sort_list[self.m_sortmode] ~= nil and
201 type(self.m_sort_list[self.m_sortmode]) == "function" then
203 self.m_sort_list[self.m_sortmode](self)
207 --------------------------------------------------------------------------------
208 function filterlist.size(self)
209 if self.m_processed_list == nil then
213 return #self.m_processed_list
216 --------------------------------------------------------------------------------
217 function filterlist.uid_exists_raw(self,uid)
218 for i,v in ipairs(self.m_raw_list) do
219 if self.m_uid_match_fct(v,uid) then
226 --------------------------------------------------------------------------------
227 function filterlist.raw_index_by_uid(self, uid)
228 local elementcount = 0
230 for i,v in ipairs(self.m_raw_list) do
231 if self.m_uid_match_fct(v,uid) then
232 elementcount = elementcount +1
238 -- If there are more elements than one with same name uid can't decide which
239 -- one is meant. self shouldn't be possible but just for sure.
240 if elementcount > 1 then
247 --------------------------------------------------------------------------------
248 -- COMMON helper functions --
249 --------------------------------------------------------------------------------
251 --------------------------------------------------------------------------------
252 function compare_worlds(world1,world2)
254 if world1.path ~= world2.path then
258 if world1.name ~= world2.name then
262 if world1.gameid ~= world2.gameid then
269 --------------------------------------------------------------------------------
270 function sort_worlds_alphabetic(self)
272 table.sort(self.m_processed_list, function(a, b)
273 --fixes issue #857 (crash due to sorting nil in worldlist)
274 if a == nil or b == nil then
275 if a == nil and b ~= nil then return false end
276 if b == nil and a ~= nil then return true end
279 if a.name:lower() == b.name:lower() then
280 return a.name < b.name
282 return a.name:lower() < b.name:lower()
286 --------------------------------------------------------------------------------
287 function sort_mod_list(self)
289 table.sort(self.m_processed_list, function(a, b)
290 -- Show game mods at bottom
291 if a.typ ~= b.typ then
292 return b.typ == "game_mod"
294 -- If in same or no modpack, sort by name
295 if a.modpack == b.modpack then
296 if a.name:lower() == b.name:lower() then
297 return a.name < b.name
299 return a.name:lower() < b.name:lower()
300 -- Else compare name to modpack name
302 -- Always show modpack pseudo-mod on top of modpack mod list
303 if a.name == b.modpack then
305 elseif b.name == a.modpack then
309 local name_a = a.modpack or a.name
310 local name_b = b.modpack or b.name
311 if name_a:lower() == name_b:lower() then
312 return name_a < name_b
314 return name_a:lower() < name_b:lower()