MicroController/stdlib/gui/gui.lua
2019-03-05 19:50:21 +08:00

134 lines
5.0 KiB
Lua

--- Gui module
-- @module Gui
require 'stdlib/event/event'
Gui = {}
-- Factorio's gui events are so monolithic we need a special event system for it.
Gui.Event = {
_registry = {},
_dispatch = {}
}
--- Registers a function for a given event and matching gui element pattern
-- @param event Valid values are defines.event.on_gui_*
-- @param gui_element_pattern the name or string regular expression to match the gui element
-- @param handler Function to call when event is triggered
-- @return #Gui.Event
function Gui.Event.register(event, gui_element_pattern, handler)
fail_if_missing(event, "missing event name argument")
fail_if_missing(gui_element_pattern, "missing gui name or pattern argument")
if type(gui_element_pattern) ~= "string" then
error("gui_element_pattern argument must be a string")
end
if handler == nil then
Gui.Event.remove(event, gui_element_pattern)
return Gui.Event
end
if not Gui.Event._registry[event] then
Gui.Event._registry[event] = {}
end
Gui.Event._registry[event][gui_element_pattern] = handler
-- Use custom Gui event dispatcher to pass off the event to the correct sub-handler
if not Gui.Event._dispatch[event] then
Event.register(event, Gui.Event.dispatch)
Gui.Event._dispatch[event] = true
end
return Gui.Event
end
--- Calls the registered handlers
-- @param event LuaEvent as created by game.raise_event
function Gui.Event.dispatch(event)
fail_if_missing(event, "missing event argument")
local gui_element = event.element
if gui_element and gui_element.valid then
local gui_element_name = gui_element.name;
local gui_element_state = nil;
local gui_element_text = nil;
if event.name == defines.events.on_gui_checked_state_changed then
gui_element_state = gui_element.state
end
if event.name == defines.events.on_gui_text_changed then
gui_element_text = gui_element.text
end
for gui_element_pattern, handler in pairs(Gui.Event._registry[event.name]) do
local match_str = string.match(gui_element_name, gui_element_pattern)
if match_str ~= nil then
local new_event = { tick = event.tick, name = event.name, _handler = handler, match = match_str, element = gui_element, state=gui_element_state, text=gui_element_text, player_index = event.player_index , _event = event}
local success, err = pcall(handler, new_event)
if not success then
Game.print_all(err)
end
end
end
end
end
--- Removes the handler with matching gui element pattern from the event
-- @param event Valid values are defines.event.on_gui_*
-- @param gui_element_pattern the name or string regular expression to remove the handler for
-- @return #Gui.Event
function Gui.Event.remove(event, gui_element_pattern)
fail_if_missing(event, "missing event argument")
fail_if_missing(gui_element_pattern, "missing gui_element_pattern argument")
if type(gui_element_pattern) ~= "string" then
error("gui_element_pattern argument must be a string")
end
local function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
if Gui.Event._registry[event] then
if Gui.Event._registry[event][gui_element_pattern] then
Gui.Event._registry[event][gui_element_pattern] = nil
end
if tablelength(Gui.Event._registry[event]) == 0 then
Event.remove(event, Gui.Event.dispatch)
Gui.Event._registry[event] = nil
Gui.Event._dispatch[event] = false
end
end
return Gui.Event
end
--- Registers a function for a given gui element name or pattern when the element is clicked
-- @param gui_element_pattern the name or string regular expression to match the gui element
-- @param handler Function to call when gui element is clicked
-- @return #Gui
function Gui.on_click(gui_element_pattern, handler)
Gui.Event.register(defines.events.on_gui_click, gui_element_pattern, handler)
return Gui
end
--- Registers a function for a given gui element name or pattern when the element checked state changes
-- @param gui_element_pattern the name or string regular expression to match the gui element
-- @param handler Function to call when gui element checked state changes
-- @return #Gui
function Gui.on_checked_state_changed(gui_element_pattern, handler)
Gui.Event.register(defines.events.on_gui_checked_state_changed, gui_element_pattern, handler)
return Gui
end
--- Registers a function for a given gui element name or pattern when the element text changes
-- @param gui_element_pattern the name or string regular expression to match the gui element
-- @param handler Function to call when gui element text changes
-- @return #Gui
function Gui.on_text_changed(gui_element_pattern, handler)
Gui.Event.register(defines.events.on_gui_text_changed, gui_element_pattern, handler)
return Gui
end