Replace worldlist by generic filterlist implementation
authorsapier <Sapier at GMX dot net>
Sun, 14 Jul 2013 11:19:37 +0000 (13:19 +0200)
committerPilzAdam <pilzadam@minetest.net>
Mon, 22 Jul 2013 16:09:59 +0000 (18:09 +0200)
builtin/mainmenu.lua
builtin/mainmenu_worldlist.lua

index 8cb786047d31fcf8665f6163935f61257460954b..91084c2c63d066bca47fab69b2c789a58c10c017 100644 (file)
@@ -10,6 +10,7 @@ dofile(scriptpath .. DIR_DELIM .. "gamemgr.lua")
 local menu = {}
 local tabbuilder = {}
 local menubar = {}
+local worldlist = nil
 
 --------------------------------------------------------------------------------
 function render_favourite(spec,render_details)
@@ -166,7 +167,7 @@ function menu.update_gametype()
                
                local gamedetails = menu.lastgame()
                engine.set_topleft_text(gamedetails.name)
-               worldlist.set_gamefilter(gamedetails.id)
+               filterlist.set_filtercriteria(worldlist,gamedetails.id)
                
                --background
                local background_set = false
@@ -208,7 +209,7 @@ end
 
 --------------------------------------------------------------------------------
 function menu.reset_gametype()
-       worldlist.set_gamefilter(nil)
+       filterlist.set_filtercriteria(worldlist,nil)
        menu.game_last_check = nil
        
        local path_background_texture = menu.basetexturedir .. "menu_background.png"
@@ -246,6 +247,27 @@ end
 function init_globals()
        --init gamedata
        gamedata.worldindex = 0
+       
+       worldlist = filterlist.create(
+                                       engine.get_worlds,
+                                       compare_worlds,
+                                       function(element,uid)
+                                               if element.name == uid then
+                                                       return true
+                                               end
+                                               return false
+                                       end, --unique id compare fct
+                                       function(element,gameid)
+                                               if element.gameid == gameid then
+                                                       return true
+                                               end
+                                               return false
+                                       end --filter fct
+                                       )
+                                       
+       filterlist.add_sort_mechanism(worldlist,"alphabetic",sort_worlds_alphabetic)
+       filterlist.set_sortmode(worldlist,"alphabetic")
+                                       
 end
 
 --------------------------------------------------------------------------------
@@ -309,7 +331,7 @@ end
 function menu.render_world_list()
        local retval = ""
        
-       local current_worldlist = worldlist.get_list()
+       local current_worldlist = filterlist.get_list(worldlist)
        
        for i,v in ipairs(current_worldlist) do
                if retval ~= "" then
@@ -371,7 +393,7 @@ end
 --------------------------------------------------------------------------------
 function menu.update_last_game()
 
-       local current_world = worldlist.get_raw_world(
+       local current_world = filterlist.get_raw_element(worldlist,
                                                        engine.setting_get("mainmenu_last_selected_world")
                                                        )
                                                        
@@ -397,17 +419,17 @@ function menu.handle_key_up_down(fields,textlist,settingname)
                if oldidx > 1 then
                        local newidx = oldidx -1
                        engine.setting_set(settingname,
-                               worldlist.get_engine_index(newidx))
+                               filterlist.get_engine_index(worldlist,newidx))
                end
        end
        
        if fields["key_down"] then
                local oldidx = engine.get_textlist_index(textlist)
                
-               if oldidx < worldlist.size() then
+               if oldidx < filterlist.size(worldlist) then
                        local newidx = oldidx + 1
                        engine.setting_set(settingname,
-                               worldlist.get_engine_index(newidx))
+                               filterlist.get_engine_index(worldlist,newidx))
                end
        end
 end
@@ -508,7 +530,7 @@ end
 
 --------------------------------------------------------------------------------
 function tabbuilder.dialog_delete_world()
-       return  "label[2,2;Delete World \"" .. worldlist.get_raw_list()[menu.world_to_del].name .. "\"?]"..
+       return  "label[2,2;Delete World \"" .. filterlist.get_raw_list(worldlist)[menu.world_to_del].name .. "\"?]"..
                        "button[3.5,4.2;2.6,0.5;world_delete_confirm;Yes]" ..
                        "button[6,4.2;2.8,0.5;world_delete_cancel;No]"
 end
@@ -570,7 +592,7 @@ function tabbuilder.handle_create_world_buttons(fields)
                        
                        local message = nil
                        
-                       if not worldlist.exists(worldname) then
+                       if not filterlist.uid_exists(worldlist,worldname) then
                                engine.setting_set("mg_name",fields["dd_mapgen"])
                                message = engine.create_world(worldname,gameindex)
                        else
@@ -583,9 +605,9 @@ function tabbuilder.handle_create_world_buttons(fields)
                                menu.last_game = gameindex
                                engine.setting_set("main_menu_last_game_idx",gameindex)
                                
-                               worldlist.refresh()
+                               filterlist.refresh(worldlist)
                                engine.setting_set("mainmenu_last_selected_world",
-                                                                       worldlist.engine_index_by_name(worldname))
+                                                                       filterlist.engine_index_by_uid(worldlist,worldname))
                        end
                else
                        gamedata.errormessage = "No worldname given or no game selected"
@@ -608,10 +630,10 @@ function tabbuilder.handle_delete_world_buttons(fields)
        
        if fields["world_delete_confirm"] then
                if menu.world_to_del > 0 and 
-                       menu.world_to_del <= #worldlist.get_raw_list() then
+                       menu.world_to_del <= #filterlist.get_raw_list(worldlist) then
                        engine.delete_world(menu.world_to_del)
                        menu.world_to_del = 0
-                       worldlist.refresh()
+                       filterlist.refresh(worldlist)
                end
        end
        
@@ -756,7 +778,7 @@ function tabbuilder.handle_server_buttons(fields)
                end
                if event.typ == "CHG" then
                        engine.setting_set("mainmenu_last_selected_world",
-                               worldlist.get_engine_index(engine.get_textlist_index("srv_worlds")))
+                               filterlist.get_engine_index(worldlist,engine.get_textlist_index("srv_worlds")))
                end
        end
        
@@ -783,7 +805,7 @@ function tabbuilder.handle_server_buttons(fields)
                        gamedata.password               = fields["te_passwd"]
                        gamedata.port                   = fields["te_serverport"]
                        gamedata.address                = ""
-                       gamedata.selected_world = worldlist.get_engine_index(selected)
+                       gamedata.selected_world = filterlist.get_engine_index(worldlist,selected)
                        
                        menu.update_last_game(gamedata.selected_world)
                        engine.start()
@@ -799,12 +821,12 @@ function tabbuilder.handle_server_buttons(fields)
        if fields["world_delete"] ~= nil then
                local selected = engine.get_textlist_index("srv_worlds")
                if selected > 0 and
-                       selected <= worldlist.size() then
-                       local world = worldlist.get_list()[selected]
+                       selected <= filterlist.size(worldlist) then
+                       local world = filterlist.get_list(worldlist)[selected]
                        if world ~= nil and
                                world.name ~= nil and
                                world.name ~= "" then
-                               menu.world_to_del = worldlist.get_engine_index(selected)
+                               menu.world_to_del = filterlist.get_engine_index(worldlist,selected)
                                tabbuilder.current_tab = "dialog_delete_world"
                                tabbuilder.is_dialog = true
                                tabbuilder.show_buttons = false
@@ -817,7 +839,7 @@ function tabbuilder.handle_server_buttons(fields)
        if fields["world_configure"] ~= nil then
                selected = engine.get_textlist_index("srv_worlds")
                if selected > 0 then
-                       modmgr.world_config_selected_world = worldlist.get_engine_index(selected)
+                       modmgr.world_config_selected_world = filterlist.get_engine_index(worldlist,selected)
                        if modmgr.init_worldconfig() then
                                tabbuilder.current_tab = "dialog_configure_world"
                                tabbuilder.is_dialog = true
@@ -897,7 +919,7 @@ function tabbuilder.handle_singleplayer_buttons(fields)
                
                if event.typ == "CHG" then
                        engine.setting_set("mainmenu_last_selected_world",
-                               worldlist.get_engine_index(engine.get_textlist_index("sp_worlds")))
+                               filterlist.get_engine_index(worldlist,engine.get_textlist_index("sp_worlds")))
                end
        end
        
@@ -916,7 +938,7 @@ function tabbuilder.handle_singleplayer_buttons(fields)
                fields["key_enter"] then
                local selected = engine.get_textlist_index("sp_worlds")
                if selected > 0 then
-                       gamedata.selected_world = worldlist.get_engine_index(selected)
+                       gamedata.selected_world = filterlist.get_engine_index(worldlist,selected)
                        gamedata.singleplayer   = true
                        
                        menu.update_last_game(gamedata.selected_world)
@@ -934,12 +956,12 @@ function tabbuilder.handle_singleplayer_buttons(fields)
        if fields["world_delete"] ~= nil then
                local selected = engine.get_textlist_index("sp_worlds")
                if selected > 0 and
-                       selected <= worldlist.size() then
-                       local world = worldlist.get_list()[selected]
+                       selected <= filterlist.size(worldlist) then
+                       local world = filterlist.get_list(worldlist)[selected]
                        if world ~= nil and
                                world.name ~= nil and
                                world.name ~= "" then
-                               menu.world_to_del = worldlist.get_engine_index(selected)
+                               menu.world_to_del = filterlist.get_engine_index(worldlist,selected)
                                tabbuilder.current_tab = "dialog_delete_world"
                                tabbuilder.is_dialog = true
                                tabbuilder.show_buttons = false
@@ -952,7 +974,7 @@ function tabbuilder.handle_singleplayer_buttons(fields)
        if fields["world_configure"] ~= nil then
                selected = engine.get_textlist_index("sp_worlds")
                if selected > 0 then
-                       modmgr.world_config_selected_world = worldlist.get_engine_index(selected)
+                       modmgr.world_config_selected_world = filterlist.get_engine_index(worldlist,selected)
                        if modmgr.init_worldconfig() then
                                tabbuilder.current_tab = "dialog_configure_world"
                                tabbuilder.is_dialog = true
@@ -1102,7 +1124,7 @@ end
 --------------------------------------------------------------------------------
 function tabbuilder.tab_server()
 
-       local index = worldlist.get_current_index(
+       local index = filterlist.get_current_index(worldlist,
                                tonumber(engine.setting_get("mainmenu_last_selected_world"))
                                )
        
@@ -1154,7 +1176,7 @@ end
 --------------------------------------------------------------------------------
 function tabbuilder.tab_singleplayer()
        
-       local index = worldlist.get_current_index(
+       local index = filterlist.get_current_index(worldlist,
                                tonumber(engine.setting_get("mainmenu_last_selected_world"))
                                )
 
@@ -1300,6 +1322,7 @@ engine.event_handler = function(event)
                        tabbuilder.is_dialog = false
                        tabbuilder.show_buttons = true
                        tabbuilder.current_tab = engine.setting_get("main_menu_tab")
+                       menu.update_gametype()
                        update_menu()
                else
                        engine.close()
@@ -1313,7 +1336,6 @@ end
 --------------------------------------------------------------------------------
 --------------------------------------------------------------------------------
 init_globals()
-worldlist.init()
 menu.init()
 tabbuilder.init()
 menubar.refresh()
index 4f7ba097c97133c12effed5c70a91c2c385d42ee..846a4793efcadc790460c908ab1719f44834f9fa 100644 (file)
-worldlist = {}
+--------------------------------------------------------------------------------
+-- Generic implementation of a filter/sortable list                           --
+--------------------------------------------------------------------------------
+filterlist = {}
 
 --------------------------------------------------------------------------------
-function worldlist.refresh()
-       worldlist.m_raw_worldlist = engine.get_worlds()
-       worldlist.process()
+function filterlist.refresh(this)
+       this.m_raw_list = this.m_raw_list_fct()
+       filterlist.process(this)
 end
 
 --------------------------------------------------------------------------------
-function worldlist.init()
-       worldlist.m_gamefilter = nil
-       worldlist.m_sortmode = "alphabetic"
+function filterlist.create(raw_fct,compare_fct,uid_match_fct,filter_fct)
+
+       assert((raw_fct ~= nil) and (type(raw_fct) == "function"))
+       assert((compare_fct ~= nil) and (type(compare_fct) == "function"))
+       
+       local this = {}
+       
+       this.m_raw_list_fct  = raw_fct
+       this.m_compare_fct   = compare_fct
+       this.m_filter_fct    = filter_fct
+       this.m_uid_match_fct = uid_match_fct
+       
+       this.m_filtercriteria = nil
+       
+       this.m_sortmode = "none"
+       this.m_sort_list = {}
+       
+       
 
-       worldlist.m_processed_worldlist = nil
-       worldlist.m_raw_worldlist = engine.get_worlds()
+       this.m_processed_list = nil
+       this.m_raw_list = this.m_raw_list_fct()
 
-       worldlist.process()
+       filterlist.process(this)
+       
+       return this
 end
 
 --------------------------------------------------------------------------------
-function worldlist.set_gamefilter(gameid)
-       if gameid == worldlist.m_gamefilter then
+function filterlist.add_sort_mechanism(this,name,fct)
+       this.m_sort_list[name] = fct
+end
+
+--------------------------------------------------------------------------------
+function filterlist.set_filtercriteria(this,criteria)
+       if criteria == this.m_filtercriteria then
                return
        end
-       worldlist.m_gamefilter = gameid
-       worldlist.process()
+       this.m_filtercriteria = criteria
+       filterlist.process(this)
 end
 
 --------------------------------------------------------------------------------
-function worldlist.get_gamefilter()
-       return worldlist.m_gamefilter
+function filterlist.get_filtercriteria(this)
+       return this.m_filtercriteria
 end
 
 --------------------------------------------------------------------------------
 --supported sort mode "alphabetic|none"
-function worldlist.set_sortmode(mode)
-       if (mode == worldlist.m_sortmode) then
+function filterlist.set_sortmode(this,mode)
+       if (mode == this.m_sortmode) then
                return
        end
-       worldlist.m_sortmode = mode
-       worldlist.process()
+       this.m_sortmode = mode
+       filterlist.process(this)
 end
 
 --------------------------------------------------------------------------------
-function worldlist.get_list()
-       return worldlist.m_processed_worldlist
+function filterlist.get_list(this)
+       return this.m_processed_list
 end
 
 --------------------------------------------------------------------------------
-function worldlist.get_raw_list()
-       return worldlist.m_raw_worldlist
+function filterlist.get_raw_list(this)
+       return this.m_raw_list
 end
 
 --------------------------------------------------------------------------------
-function worldlist.get_raw_world(idx)
+function filterlist.get_raw_element(this,idx)
        if type(idx) ~= "number" then
                idx = tonumber(idx)
        end
        
-       if idx ~= nil and idx > 0 and idx < #worldlist.m_raw_worldlist then
-               return worldlist.m_raw_worldlist[idx]
+       if idx ~= nil and idx > 0 and idx < #this.m_raw_list then
+               return this.m_raw_list[idx]
        end
        
        return nil
 end
 
 --------------------------------------------------------------------------------
-function worldlist.get_engine_index(worldlistindex)
-       assert(worldlist.m_processed_worldlist ~= nil)
+function filterlist.get_engine_index(this,listindex)
+       assert(this.m_processed_list ~= nil)
        
-       if worldlistindex ~= nil and worldlistindex > 0 and
-               worldlistindex <= #worldlist.m_processed_worldlist then
-               local entry = worldlist.m_processed_worldlist[worldlistindex]
+       if listindex ~= nil and listindex > 0 and
+               listindex <= #this.m_processed_list then
+               local entry = this.m_processed_list[listindex]
                
-               for i,v in ipairs(worldlist.m_raw_worldlist) do
+               for i,v in ipairs(this.m_raw_list) do
                
-                       if worldlist.compare(v,entry) then
+                       if this.m_compare_fct(v,entry) then
                                return i
                        end
                end
@@ -84,16 +109,16 @@ function worldlist.get_engine_index(worldlistindex)
 end
 
 --------------------------------------------------------------------------------
-function worldlist.get_current_index(worldlistindex)
-       assert(worldlist.m_processed_worldlist ~= nil)
+function filterlist.get_current_index(this,listindex)
+       assert(this.m_processed_list ~= nil)
        
-       if worldlistindex ~= nil and worldlistindex > 0 and
-               worldlistindex <= #worldlist.m_raw_worldlist then
-               local entry = worldlist.m_raw_worldlist[worldlistindex]
+       if listindex ~= nil and listindex > 0 and
+               listindex <= #this.m_raw_list then
+               local entry = this.m_raw_list[listindex]
                
-               for i,v in ipairs(worldlist.m_processed_worldlist) do
+               for i,v in ipairs(this.m_processed_list) do
                
-                       if worldlist.compare(v,entry) then
+                       if this.m_compare_fct(v,entry) then
                                return i
                        end
                end
@@ -103,98 +128,102 @@ function worldlist.get_current_index(worldlistindex)
 end
 
 --------------------------------------------------------------------------------
-function worldlist.process()
-       assert(worldlist.m_raw_worldlist ~= nil)
+function filterlist.process(this)
+       assert(this.m_raw_list ~= nil)
 
-       if worldlist.m_sortmode == "none" and 
-          worldlist.m_gamefilter == nil then
-               worldlist.m_processed_worldlist = worldlist.m_raw_worldlist
+       if this.m_sortmode == "none" and
+               this.m_filtercriteria == nil then
+               this.m_processed_list = this.m_raw_list
                return
        end
        
-       worldlist.m_processed_worldlist = {}
+       this.m_processed_list = {}
        
-       for i,v in ipairs(worldlist.m_raw_worldlist) do
+       for i,v in ipairs(this.m_raw_list) do
        
-               if worldlist.m_gamefilter == nil or 
-                       v.gameid == worldlist.m_gamefilter then
-                       table.insert(worldlist.m_processed_worldlist,v)
+               if this.m_filtercriteria == nil or 
+                       this.m_filter_fct(v,this.m_filtercriteria) then
+                       table.insert(this.m_processed_list,v)
                end
        end
        
-       if worldlist.m_sortmode == "none" then
+       if this.m_sortmode == "none" then
                return
        end
        
-       if worldlist.m_sortmode == "alphabetic" then
-               worldlist.sort_alphabetic()
-       end
-
-end
-
---------------------------------------------------------------------------------
-function worldlist.compare(world1,world2)
-
-       if world1.path ~= world2.path then
-               return false
-       end
-       
-       if world1.name ~= world2.name then
-               return false
-       end
-       
-       if world1.gameid ~= world2.gameid then
-               return false
+       if this.m_sort_list[this.m_sortmode] ~= nil and 
+               type(this.m_sort_list[this.m_sortmode]) == "function" then
+               
+               this.m_sort_list[this.m_sortmode](this)
        end
-
-       return true
 end
 
 --------------------------------------------------------------------------------
-function worldlist.size()
-       if worldlist.m_processed_worldlist == nil then
+function filterlist.size(this)
+       if this.m_processed_list == nil then
                return 0
        end
        
-       return #worldlist.m_processed_worldlist
+       return #this.m_processed_list
 end
 
 --------------------------------------------------------------------------------
-function worldlist.exists(worldname)
-       for i,v in ipairs(worldlist.m_raw_worldlist) do
-               if v.name == worldname then
+function filterlist.uid_exists_raw(this,uid)
+       for i,v in ipairs(this.m_raw_list) do
+               if this.m_uid_match_fct(v,uid) then
                        return true
                end
        end
        return false
 end
 
-
 --------------------------------------------------------------------------------
-function worldlist.engine_index_by_name(worldname)
-       local worldcount = 0
-       local worldidx = 0
-       for i,v in ipairs(worldlist.m_raw_worldlist) do
-               if v.name == worldname then
-                       worldcount = worldcount +1
-                       worldidx = i
+function filterlist.engine_index_by_uid(this, uid)
+       local elementcount = 0
+       local elementidx = 0
+       for i,v in ipairs(this.m_raw_list) do
+               if this.m_uid_match_fct(v,uid) then
+                       elementcount = elementcount +1
+                       elementidx = i
                end
        end
        
        
-       -- If there are more worlds than one with same name we can't decide which
+       -- If there are more elements than one with same name uid can't decide which
        -- one is meant. This shouldn't be possible but just for sure.
-       if worldcount > 1 then
-               worldidx=0
+       if elementcount > 1 then
+               elementidx=0
+       end
+
+       return elementidx
+end
+
+--------------------------------------------------------------------------------
+-- COMMON helper functions                                                    --
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+function compare_worlds(world1,world2)
+
+       if world1.path ~= world2.path then
+               return false
+       end
+       
+       if world1.name ~= world2.name then
+               return false
+       end
+       
+       if world1.gameid ~= world2.gameid then
+               return false
        end
 
-       return worldidx
+       return true
 end
 
 --------------------------------------------------------------------------------
-function worldlist.sort_alphabetic(
+function sort_worlds_alphabetic(this
 
-       table.sort(worldlist.m_processed_worldlist, function(a, b) 
+       table.sort(this.m_processed_list, function(a, b) 
                        local n1 = a.name 
                        local n2 = b.name 
                        local count = math.min(#n1, #n2)