]> git.lizzy.rs Git - dragonfireclient.git/blob - builtin/filterlist.lua
Remove link to #, add unlimited_player_transfer_distance to announce
[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 --------------------------------------------------------------------------------
21 filterlist = {}
22
23 --------------------------------------------------------------------------------
24 function filterlist.refresh(this)
25         this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
26         filterlist.process(this)
27 end
28
29 --------------------------------------------------------------------------------
30 function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct,fetch_param)
31
32         assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
33         assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
34         
35         local this = {}
36         
37         this.m_raw_list_fct  = raw_fct
38         this.m_compare_fct   = compare_fct
39         this.m_filter_fct    = filter_fct
40         this.m_uid_match_fct = uid_match_fct
41         
42         this.m_filtercriteria = nil
43         this.m_fetch_param = fetch_param
44         
45         this.m_sortmode = "none"
46         this.m_sort_list = {}
47
48         this.m_processed_list = nil
49         this.m_raw_list = this.m_raw_list_fct(this.m_fetch_param)
50
51         filterlist.process(this)
52         
53         return this
54 end
55
56 --------------------------------------------------------------------------------
57 function filterlist.add_sort_mechanism(this,name,fct)
58         this.m_sort_list[name] = fct
59 end
60
61 --------------------------------------------------------------------------------
62 function filterlist.set_filtercriteria(this,criteria)
63         if criteria == this.m_filtercriteria and
64                 type(criteria) ~= "table" then
65                 return
66         end
67         this.m_filtercriteria = criteria
68         filterlist.process(this)
69 end
70
71 --------------------------------------------------------------------------------
72 function filterlist.get_filtercriteria(this)
73         return this.m_filtercriteria
74 end
75
76 --------------------------------------------------------------------------------
77 --supported sort mode "alphabetic|none"
78 function filterlist.set_sortmode(this,mode)
79         if (mode == this.m_sortmode) then
80                 return
81         end
82         this.m_sortmode = mode
83         filterlist.process(this)
84 end
85
86 --------------------------------------------------------------------------------
87 function filterlist.get_list(this)
88         return this.m_processed_list
89 end
90
91 --------------------------------------------------------------------------------
92 function filterlist.get_raw_list(this)
93         return this.m_raw_list
94 end
95
96 --------------------------------------------------------------------------------
97 function filterlist.get_raw_element(this,idx)
98         if type(idx) ~= "number" then
99                 idx = tonumber(idx)
100         end
101         
102         if idx ~= nil and idx > 0 and idx < #this.m_raw_list then
103                 return this.m_raw_list[idx]
104         end
105         
106         return nil
107 end
108
109 --------------------------------------------------------------------------------
110 function filterlist.get_raw_index(this,listindex)
111         assert(this.m_processed_list ~= nil)
112         
113         if listindex ~= nil and listindex > 0 and
114                 listindex <= #this.m_processed_list then
115                 local entry = this.m_processed_list[listindex]
116                 
117                 for i,v in ipairs(this.m_raw_list) do
118                 
119                         if this.m_compare_fct(v,entry) then
120                                 return i
121                         end
122                 end
123         end
124         
125         return 0
126 end
127
128 --------------------------------------------------------------------------------
129 function filterlist.get_current_index(this,listindex)
130         assert(this.m_processed_list ~= nil)
131         
132         if listindex ~= nil and listindex > 0 and
133                 listindex <= #this.m_raw_list then
134                 local entry = this.m_raw_list[listindex]
135                 
136                 for i,v in ipairs(this.m_processed_list) do
137                 
138                         if this.m_compare_fct(v,entry) then
139                                 return i
140                         end
141                 end
142         end
143         
144         return 0
145 end
146
147 --------------------------------------------------------------------------------
148 function filterlist.process(this)
149         assert(this.m_raw_list ~= nil)
150
151         if this.m_sortmode == "none" and
152                 this.m_filtercriteria == nil then
153                 this.m_processed_list = this.m_raw_list
154                 return
155         end
156         
157         this.m_processed_list = {}
158         
159         for k,v in pairs(this.m_raw_list) do
160                 if this.m_filtercriteria == nil or 
161                         this.m_filter_fct(v,this.m_filtercriteria) then
162                         table.insert(this.m_processed_list,v)
163                 end
164         end
165         
166         if this.m_sortmode == "none" then
167                 return
168         end
169         
170         if this.m_sort_list[this.m_sortmode] ~= nil and 
171                 type(this.m_sort_list[this.m_sortmode]) == "function" then
172                 
173                 this.m_sort_list[this.m_sortmode](this)
174         end
175 end
176
177 --------------------------------------------------------------------------------
178 function filterlist.size(this)
179         if this.m_processed_list == nil then
180                 return 0
181         end
182         
183         return #this.m_processed_list
184 end
185
186 --------------------------------------------------------------------------------
187 function filterlist.uid_exists_raw(this,uid)
188         for i,v in ipairs(this.m_raw_list) do
189                 if this.m_uid_match_fct(v,uid) then
190                         return true
191                 end
192         end
193         return false
194 end
195
196 --------------------------------------------------------------------------------
197 function filterlist.raw_index_by_uid(this, uid)
198         local elementcount = 0
199         local elementidx = 0
200         for i,v in ipairs(this.m_raw_list) do
201                 if this.m_uid_match_fct(v,uid) then
202                         elementcount = elementcount +1
203                         elementidx = i
204                 end
205         end
206         
207         
208         -- If there are more elements than one with same name uid can't decide which
209         -- one is meant. This shouldn't be possible but just for sure.
210         if elementcount > 1 then
211                 elementidx=0
212         end
213
214         return elementidx
215 end
216
217 --------------------------------------------------------------------------------
218 -- COMMON helper functions                                                    --
219 --------------------------------------------------------------------------------
220
221 --------------------------------------------------------------------------------
222 function compare_worlds(world1,world2)
223
224         if world1.path ~= world2.path then
225                 return false
226         end
227         
228         if world1.name ~= world2.name then
229                 return false
230         end
231         
232         if world1.gameid ~= world2.gameid then
233                 return false
234         end
235
236         return true
237 end
238
239 --------------------------------------------------------------------------------
240 function sort_worlds_alphabetic(this) 
241
242         table.sort(this.m_processed_list, function(a, b)
243                 --fixes issue #857 (crash due to sorting nil in worldlist)
244                 if a == nil or b == nil then
245                         if a == nil and b ~= nil then return false end
246                         if b == nil and a ~= nil then return true end
247                         return false
248                 end
249                 if a.name:lower() == b.name:lower() then
250                         return a.name < b.name
251                 end
252                 return a.name:lower() < b.name:lower()
253         end)
254 end
255
256 --------------------------------------------------------------------------------
257 function sort_mod_list(this)
258
259         table.sort(this.m_processed_list, function(a, b)
260                 -- Show game mods at bottom
261                 if a.typ ~= b.typ then
262                         return b.typ == "game_mod"
263                 end
264                 -- If in same or no modpack, sort by name
265                 if a.modpack == b.modpack then
266                         if a.name:lower() == b.name:lower() then
267                                 return a.name < b.name
268                         end
269                         return a.name:lower() < b.name:lower()
270                 -- Else compare name to modpack name
271                 else
272                         -- Always show modpack pseudo-mod on top of modpack mod list
273                         if a.name == b.modpack then
274                                 return true
275                         elseif b.name == a.modpack then
276                                 return false
277                         end
278                         
279                         local name_a = a.modpack or a.name
280                         local name_b = b.modpack or b.name
281                         if name_a:lower() == name_b:lower() then
282                                 return  name_a < name_b
283                         end
284                         return name_a:lower() < name_b:lower()
285                 end
286         end)
287 end