220 lines
6.5 KiB
Lua
220 lines
6.5 KiB
Lua
-- -------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- RAILUALIB GUI MODULE
|
|
-- GUI templating and event registration.
|
|
|
|
-- dependencies
|
|
local event = require("__RaiLuaLib__.lualib.event")
|
|
local util = require("__core__.lualib.util")
|
|
|
|
-- locals
|
|
local string_gmatch = string.gmatch
|
|
|
|
local handler_data = {}
|
|
|
|
-- object
|
|
local gui = {}
|
|
local handlers = {}
|
|
local templates = {}
|
|
local template_lookup = {}
|
|
|
|
-- -----------------------------------------------------------------------------
|
|
-- TABLE OBJECTS
|
|
|
|
local function extend_table(self, data, do_return)
|
|
for k, v in pairs(data) do
|
|
if (type(v) == "table") then
|
|
if (type(self[k] or false) == "table") then
|
|
self[k] = extend_table(self[k], v, true)
|
|
else
|
|
self[k] = table.deepcopy(v)
|
|
end
|
|
else
|
|
self[k] = v
|
|
end
|
|
end
|
|
if do_return then return self end
|
|
end
|
|
|
|
handlers.extend = extend_table
|
|
templates.extend = extend_table
|
|
|
|
-- -----------------------------------------------------------------------------
|
|
-- HANDLERS AND TEMPLATES
|
|
|
|
-- generate one-dimensional template lookup table
|
|
local function generate_template_lookup(t, template_string)
|
|
for k,v in pairs(t) do
|
|
if k ~= "extend" and type(v) == "table" then
|
|
local new_string = template_string..k
|
|
if v.type then
|
|
template_lookup[new_string] = v
|
|
else
|
|
generate_template_lookup(v, new_string..".")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- recursively navigate the handlers table to create the events
|
|
local function generate_handlers(t, event_string, event_groups)
|
|
event_groups[#event_groups+1] = event_string
|
|
for k,v in pairs(t) do
|
|
if k ~= "extend" then
|
|
local new_string = event_string.."."..k
|
|
if type(v) == "function" then
|
|
-- shortcut syntax: key is a defines.events or a custom-input name, value is just the handler
|
|
handler_data[new_string] = {id=defines.events[k] or k, handler=v, group=table.deepcopy(event_groups)}
|
|
elseif v.handler then
|
|
if not v.id then
|
|
v.id = defines.events[k] or k
|
|
end
|
|
v.group = table.deepcopy(event_groups)
|
|
handler_data[new_string] = v
|
|
else
|
|
generate_handlers(v, new_string, event_groups)
|
|
end
|
|
end
|
|
end
|
|
event_groups[#event_groups] = nil
|
|
end
|
|
|
|
-- create template lookup and register conditional GUI handlers
|
|
event.register({"on_init_postprocess", "on_load_postprocess"}, function(e)
|
|
-- construct template lookup table
|
|
generate_template_lookup(templates, "")
|
|
-- create and register conditional handlers for the GUI events
|
|
generate_handlers(handlers, "gui", {})
|
|
event.register_conditional(handler_data)
|
|
end)
|
|
|
|
-- -----------------------------------------------------------------------------
|
|
-- GUI CONSTRUCTION
|
|
|
|
-- recursively load a GUI template
|
|
local function recursive_build(parent, t, output, filters, player_index)
|
|
-- load template
|
|
if t.template then
|
|
for k,v in pairs(template_lookup[t.template]) do
|
|
t[k] = t[k] or v
|
|
end
|
|
end
|
|
local elem
|
|
-- special logic if this is a tab-and-content
|
|
if t.type == "tab-and-content" then
|
|
local tab, content
|
|
output, filters, tab = recursive_build(parent, t.tab, output, filters, player_index)
|
|
output, filters, content = recursive_build(parent, t.content, output, filters, player_index)
|
|
parent.add_tab(tab, content)
|
|
else
|
|
-- create element
|
|
elem = parent.add(t)
|
|
-- apply style modifications
|
|
if t.style_mods then
|
|
for k,v in pairs(t.style_mods) do
|
|
elem.style[k] = v
|
|
end
|
|
end
|
|
-- apply modifications
|
|
if t.mods then
|
|
for k,v in pairs(t.mods) do
|
|
elem[k] = v
|
|
end
|
|
end
|
|
-- register handlers
|
|
if t.handlers then
|
|
local elem_index = elem.index
|
|
local name = "gui."..t.handlers
|
|
local group = event.conditional_event_groups[name]
|
|
if not group then error("Invalid GUI event group: "..name) end
|
|
-- check if this event group was already enabled
|
|
if event.is_enabled(group[1], player_index) then
|
|
-- append the GUI filters to include this element
|
|
for i=1,#group do
|
|
event.update_gui_filters(group[i], player_index, elem_index, "add")
|
|
if filters[name] then
|
|
filters[name][elem_index] = elem_index
|
|
else
|
|
filters[name] = {[elem_index]=elem_index}
|
|
end
|
|
end
|
|
else
|
|
-- enable the group
|
|
event.enable_group(name, player_index, elem_index)
|
|
filters[name] = {[elem_index]=elem_index}
|
|
end
|
|
end
|
|
-- add to output table
|
|
if t.save_as then
|
|
-- recursively create tables as needed
|
|
local prev = output
|
|
local prev_key
|
|
local nav
|
|
for key in string_gmatch(t.save_as, "([^%.]+)") do
|
|
prev = prev_key and prev[prev_key] or prev
|
|
nav = prev[key]
|
|
if nav then
|
|
prev = nav
|
|
else
|
|
prev[key] = {}
|
|
prev_key = key
|
|
end
|
|
end
|
|
prev[prev_key] = elem
|
|
end
|
|
-- add children
|
|
local children = t.children
|
|
if children then
|
|
for i=1,#children do
|
|
output, filters = recursive_build(elem, children[i], output, filters, player_index)
|
|
end
|
|
end
|
|
end
|
|
return output, filters, elem
|
|
end
|
|
|
|
-- -- updates the GUI based on the template
|
|
-- local function recursive_update(parent, t, player_index)
|
|
-- local children = parent.children
|
|
-- local to_destroy = {}
|
|
-- for i=1,#t do
|
|
-- local elem = children[i]
|
|
-- local elem_t = t[i]
|
|
-- if elem_t.delete then
|
|
-- to_destroy[#to_destroy+1] = elem
|
|
-- else
|
|
-- for k,v in pairs(elem_t.mods or {}) do
|
|
-- if k ~= "children" then
|
|
-- elem[k] = v
|
|
-- end
|
|
-- end
|
|
-- local elem_style = elem.style
|
|
-- for k,v in pairs(elem_t.style_mods or {}) do
|
|
-- elem_style[k] = v
|
|
-- end
|
|
-- if elem_t.children then
|
|
-- recursive_update(elem, elem_t.children, player_index)
|
|
-- end
|
|
-- end
|
|
-- end
|
|
-- end
|
|
|
|
-- -----------------------------------------------------------------------------
|
|
-- OBJECT
|
|
|
|
function gui.build(parent, templates)
|
|
local output = {}
|
|
local filters = {}
|
|
for i=1,#templates do
|
|
output, filters = recursive_build(parent, templates[i], output, filters, parent.player_index or parent.player.index)
|
|
end
|
|
return output, filters
|
|
end
|
|
|
|
-- function gui.update(parent, templates)
|
|
-- recursive_update(parent, templates, parent.player_index or parent.player.index)
|
|
-- end
|
|
|
|
gui.templates = templates
|
|
gui.handlers = handlers
|
|
|
|
return gui |