]> git.lizzy.rs Git - dragonfireclient.git/blob - builtin/filterlist.lua
Add forceloading
[dragonfireclient.git] / builtin / filterlist.lua
1 --Minetest
2 --Copyright (C) 2013 sapier
3 --
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.
8 --
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.
13 --
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.
17
18 --------------------------------------------------------------------------------
19 -- Generic implementation of a filter/sortable list                           --
20 -- Usage:                                                                     --
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                 --
33 --                                                                            --
34 --------------------------------------------------------------------------------
35 filterlist = {}
36
37 --------------------------------------------------------------------------------
38 function filterlist.refresh(this)
39         this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
40         filterlist.process(this)
41 end
42
43 --------------------------------------------------------------------------------
44 function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
45
46         assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
47         assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
48         
49         local this = {}
50         
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
55         
56         this.m_filtercriteria = nil
57         this.m_fetch_param = fetch_param
58         
59         this.m_sortmode = "none"
60         this.m_sort_list = {}
61
62         this.m_processed_list = nil
63         this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
64
65         filterlist.process(this)
66         
67         return this
68 end
69
70 --------------------------------------------------------------------------------
71 function filterlist.add_sort_mechanism(this,name,fct)
72         this.m_sort_list[name] = fct
73 end
74
75 --------------------------------------------------------------------------------
76 function filterlist.set_filtercriteria(this,criteria)
77         if criteria == this.m_filtercriteria and
78                 type(criteria) ~= "table" then
79                 return
80         end
81         this.m_filtercriteria = criteria
82         filterlist.process(this)
83 end
84
85 --------------------------------------------------------------------------------
86 function filterlist.get_filtercriteria(this)
87         return this.m_filtercriteria
88 end
89
90 --------------------------------------------------------------------------------
91 --supported sort mode "alphabetic|none"
92 function filterlist.set_sortmode(this,mode)
93         if (mode == this.m_sortmode) then
94                 return
95         end
96         this.m_sortmode = mode
97         filterlist.process(this)
98 end
99
100 --------------------------------------------------------------------------------
101 function filterlist.get_list(this)
102         return this.m_processed_list
103 end
104
105 --------------------------------------------------------------------------------
106 function filterlist.get_raw_list(this)
107         return this.m_raw_list
108 end
109
110 --------------------------------------------------------------------------------
111 function filterlist.get_raw_element(this,idx)
112         if type(idx) ~= "number" then
113                 idx = tonumber(idx)
114         end
115         
116         if idx ~= nil and idx > 0 and idx < #this.m_raw_list then
117                 return this.m_raw_list[idx]
118         end
119         
120         return nil
121 end
122
123 --------------------------------------------------------------------------------
124 function filterlist.get_raw_index(this,listindex)
125         assert(this.m_processed_list ~= nil)
126         
127         if listindex ~= nil and listindex > 0 and
128                 listindex <= #this.m_processed_list then
129                 local entry = this.m_processed_list[listindex]
130                 
131                 for i,v in ipairs(this.m_raw_list) do
132                 
133                         if this.m_compare_fct(v,entry) then
134                                 return i
135                         end
136                 end
137         end
138         
139         return 0
140 end
141
142 --------------------------------------------------------------------------------
143 function filterlist.get_current_index(this,listindex)
144         assert(this.m_processed_list ~= nil)
145         
146         if listindex ~= nil and listindex > 0 and
147                 listindex <= #this.m_raw_list then
148                 local entry = this.m_raw_list[listindex]
149                 
150                 for i,v in ipairs(this.m_processed_list) do
151                 
152                         if this.m_compare_fct(v,entry) then
153                                 return i
154                         end
155                 end
156         end
157         
158         return 0
159 end
160
161 --------------------------------------------------------------------------------
162 function filterlist.process(this)
163         assert(this.m_raw_list ~= nil)
164
165         if this.m_sortmode == "none" and
166                 this.m_filtercriteria == nil then
167                 this.m_processed_list = this.m_raw_list
168                 return
169         end
170         
171         this.m_processed_list = {}
172         
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)
177                 end
178         end
179         
180         if this.m_sortmode == "none" then
181                 return
182         end
183         
184         if this.m_sort_list[this.m_sortmode] ~= nil and
185                 type(this.m_sort_list[this.m_sortmode]) == "function" then
186                 
187                 this.m_sort_list[this.m_sortmode](this)
188         end
189 end
190
191 --------------------------------------------------------------------------------
192 function filterlist.size(this)
193         if this.m_processed_list == nil then
194                 return 0
195         end
196         
197         return #this.m_processed_list
198 end
199
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
204                         return true
205                 end
206         end
207         return false
208 end
209
210 --------------------------------------------------------------------------------
211 function filterlist.raw_index_by_uid(this, uid)
212         local elementcount = 0
213         local elementidx = 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
217                         elementidx = i
218                 end
219         end
220         
221         
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
225                 elementidx=0
226         end
227
228         return elementidx
229 end
230
231 --------------------------------------------------------------------------------
232 -- COMMON helper functions                                                    --
233 --------------------------------------------------------------------------------
234
235 --------------------------------------------------------------------------------
236 function compare_worlds(world1,world2)
237
238         if world1.path ~= world2.path then
239                 return false
240         end
241         
242         if world1.name ~= world2.name then
243                 return false
244         end
245         
246         if world1.gameid ~= world2.gameid then
247                 return false
248         end
249
250         return true
251 end
252
253 --------------------------------------------------------------------------------
254 function sort_worlds_alphabetic(this)
255
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
261                         return false
262                 end
263                 if a.name:lower() == b.name:lower() then
264                         return a.name < b.name
265                 end
266                 return a.name:lower() < b.name:lower()
267         end)
268 end
269
270 --------------------------------------------------------------------------------
271 function sort_mod_list(this)
272
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"
277                 end
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
282                         end
283                         return a.name:lower() < b.name:lower()
284                 -- Else compare name to modpack name
285                 else
286                         -- Always show modpack pseudo-mod on top of modpack mod list
287                         if a.name == b.modpack then
288                                 return true
289                         elseif b.name == a.modpack then
290                                 return false
291                         end
292                         
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
297                         end
298                         return name_a:lower() < name_b:lower()
299                 end
300         end)
301 end