mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Add core elements
This commit is contained in:
215
exp_gui/module/control.lua
Normal file
215
exp_gui/module/control.lua
Normal file
@@ -0,0 +1,215 @@
|
||||
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
local ExpElement = require("modules/exp_gui/prototype")
|
||||
|
||||
--- @alias ExpGui.VisibleCallback fun(player: LuaPlayer, element: LuaGuiElement): boolean
|
||||
|
||||
--- @class ExpGui.player_elements
|
||||
--- @field top table<string, LuaGuiElement?>
|
||||
--- @field left table<string, LuaGuiElement?>
|
||||
--- @field relative table<string, LuaGuiElement?>
|
||||
|
||||
--- @type table<uint, ExpGui.player_elements>
|
||||
local player_elements = {}
|
||||
Storage.register(player_elements, function(tbl)
|
||||
player_elements = tbl
|
||||
end)
|
||||
|
||||
--- @class ExpGui
|
||||
local ExpGui = {
|
||||
element = ExpElement.create,
|
||||
property_from_args = ExpElement.property_from_args,
|
||||
property_from_name = ExpElement.property_from_name,
|
||||
top_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
left_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
relative_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
}
|
||||
|
||||
local mod_gui = require("mod-gui")
|
||||
ExpGui.get_top_flow = mod_gui.get_button_flow
|
||||
ExpGui.get_left_flow = mod_gui.get_frame_flow
|
||||
|
||||
--- Get a player from an element or gui event
|
||||
--- @param input LuaGuiElement | { player_index: uint }
|
||||
--- @return LuaPlayer
|
||||
function ExpGui.get_player(input)
|
||||
return assert(game.get_player(input.player_index))
|
||||
end
|
||||
|
||||
--- Toggle the enable state of an element
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
--- @return boolean
|
||||
function ExpGui.toggle_enabled_state(element, state)
|
||||
if not element or not element.valid then return false end
|
||||
if state == nil then
|
||||
state = not element.enabled
|
||||
end
|
||||
element.enabled = state
|
||||
return state
|
||||
end
|
||||
|
||||
--- Toggle the visibility of an element
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
--- @return boolean
|
||||
function ExpGui.toggle_visible_state(element, state)
|
||||
if not element or not element.valid then return false end
|
||||
if state == nil then
|
||||
state = not element.visible
|
||||
end
|
||||
element.visible = state
|
||||
return state
|
||||
end
|
||||
|
||||
--- Destroy an element if it exists and is valid
|
||||
--- @param element LuaGuiElement?
|
||||
function ExpGui.destroy_if_valid(element)
|
||||
if not element or not element.valid then return end
|
||||
element.destroy()
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the top flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_top_element(define, visible)
|
||||
assert(ExpGui.top_elements[define.name] == nil, "Element is already added to the top flow")
|
||||
ExpGui.top_elements[define] = visible or false
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_left_element(define, visible)
|
||||
assert(ExpGui.left_elements[define.name] == nil, "Element is already added to the left flow")
|
||||
ExpGui.left_elements[define] = visible or false
|
||||
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_relative_element(define, visible)
|
||||
assert(ExpGui.relative_elements[define.name] == nil, "Element is already added to the relative flow")
|
||||
ExpGui.relative_elements[define] = visible or false
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the top flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_top_element(define, player)
|
||||
return player_elements[player.index].top[define.name]
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_left_element(define, player)
|
||||
return player_elements[player.index].left[define.name]
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_relative_element(define, player)
|
||||
return player_elements[player.index].relative[define.name]
|
||||
end
|
||||
|
||||
--- Return all top level elements for a player
|
||||
---@param player LuaPlayer
|
||||
---@return ExpGui.player_elements
|
||||
function ExpGui._get_player_elements(player)
|
||||
return player_elements[player.index]
|
||||
end
|
||||
|
||||
--- Ensure all the correct elements are visible and exist
|
||||
--- @param player LuaPlayer
|
||||
--- @param element_defines table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
--- @param elements table<string, LuaGuiElement?>
|
||||
--- @param parent LuaGuiElement
|
||||
local function ensure_elements(player, element_defines, elements, parent)
|
||||
local done = {}
|
||||
for define, visible in pairs(element_defines) do
|
||||
local element = elements[define.name]
|
||||
if not element then
|
||||
element = define(parent)
|
||||
elements[define.name] = element
|
||||
assert(element, "Element define did not return an element: " .. define.name)
|
||||
end
|
||||
|
||||
if type(visible) == "function" then
|
||||
visible = visible(player, element)
|
||||
end
|
||||
element.visible = visible
|
||||
done[define.name] = true
|
||||
end
|
||||
|
||||
for name, element in pairs(elements) do
|
||||
if not done[name] then
|
||||
element.destroy()
|
||||
elements[name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Ensure all elements have been created
|
||||
--- @param event EventData.on_player_created | EventData.on_player_joined_game
|
||||
function ExpGui._ensure_elements(event)
|
||||
local player = assert(game.get_player(event.player_index))
|
||||
local elements = player_elements[event.player_index]
|
||||
if not elements then
|
||||
elements = {
|
||||
top = {},
|
||||
left = {},
|
||||
relative = {},
|
||||
}
|
||||
player_elements[event.player_index] = elements
|
||||
end
|
||||
|
||||
ensure_elements(player, ExpGui.top_elements, elements.top, ExpGui.get_top_flow(player))
|
||||
ensure_elements(player, ExpGui.left_elements, elements.left, ExpGui.get_left_flow(player))
|
||||
ensure_elements(player, ExpGui.relative_elements, elements.relative, player.gui.relative)
|
||||
|
||||
-- Check technically not needed, but makes it easier to use this lib without the core defines
|
||||
if ExpGui.apply_consistency_checks then
|
||||
ExpGui.apply_consistency_checks(player, true)
|
||||
end
|
||||
end
|
||||
|
||||
--- Rerun the visible check for relative elements
|
||||
--- @param event EventData.on_gui_opened
|
||||
local function on_gui_opened(event)
|
||||
local player = ExpGui.get_player(event)
|
||||
local original_element = event.element
|
||||
|
||||
for define, visible in pairs(ExpGui.relative_elements) do
|
||||
local element = ExpGui.get_relative_element(define, player)
|
||||
|
||||
if type(visible) == "function" then
|
||||
visible = visible(player, element)
|
||||
end
|
||||
element.visible = visible
|
||||
|
||||
if visible then
|
||||
event.element = element
|
||||
--- @diagnostic disable-next-line invisible
|
||||
define:_raise_event(event)
|
||||
end
|
||||
end
|
||||
|
||||
event.element = original_element
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
local events = {
|
||||
[e.on_player_created] = ExpGui._ensure_elements,
|
||||
[e.on_player_joined_game] = ExpGui._ensure_elements,
|
||||
[e.on_gui_opened] = on_gui_opened,
|
||||
}
|
||||
|
||||
ExpGui.events = events
|
||||
return ExpGui
|
||||
289
exp_gui/module/core_elements.lua
Normal file
289
exp_gui/module/core_elements.lua
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
--- @class ExpGui
|
||||
local ExpGui = require("modules/exp_gui")
|
||||
local mod_gui = require("mod-gui")
|
||||
|
||||
local toolbar_button_default_style = mod_gui.button_style
|
||||
local toolbar_button_active_style = "menu_button_continue"
|
||||
local toolbar_button_size = 36
|
||||
|
||||
local elements = {} --- @type table<string, ExpElement>
|
||||
local buttons_with_left_element = {} --- @type table<string, ExpElement>
|
||||
local left_elements_with_button = {} --- @type table<string, ExpElement>
|
||||
|
||||
--- Set the style of a toolbar button
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
--- @return boolean
|
||||
function ExpGui.set_toolbar_button_style(element, state)
|
||||
if state == nil then state = element.style.name == toolbar_button_default_style end
|
||||
element.style = state and toolbar_button_active_style or toolbar_button_default_style
|
||||
|
||||
local style = element.style
|
||||
style.minimal_width = toolbar_button_size
|
||||
style.height = toolbar_button_size
|
||||
if element.type == "sprite-button" then
|
||||
style.padding = -2
|
||||
else
|
||||
style.font = "default-semibold"
|
||||
style.padding = 0
|
||||
end
|
||||
|
||||
return state
|
||||
end
|
||||
|
||||
--- Set the visible state of the top flow for a player
|
||||
--- @param player LuaPlayer
|
||||
--- @param state boolean?
|
||||
function ExpGui.set_top_flow_visible(player, state)
|
||||
local top_flow = assert(ExpGui.get_top_flow(player).parent, player.name)
|
||||
local show_top_flow = elements.core_button_flow.data[player].show_top_flow --- @type LuaGuiElement
|
||||
|
||||
if state == nil then
|
||||
state = not top_flow.visible
|
||||
end
|
||||
|
||||
top_flow.visible = state
|
||||
show_top_flow.visible = not state
|
||||
end
|
||||
|
||||
--- Set the visible state of the left element for a player
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @param state boolean?
|
||||
function ExpGui.set_left_element_visible(define, player, state)
|
||||
local element = assert(ExpGui.get_left_element(define, player), "Define is not added to the left flow")
|
||||
local clear_left_flow = elements.core_button_flow.data[player].clear_left_flow --- @type LuaGuiElement
|
||||
|
||||
-- Update the visible state
|
||||
if state == nil then state = not element.visible end
|
||||
element.visible = state
|
||||
|
||||
-- Check if there is a toolbar button linked to this element
|
||||
local toolbar_button = left_elements_with_button[define.name]
|
||||
if toolbar_button then
|
||||
ExpGui.set_toolbar_button_style(ExpGui.get_top_element(toolbar_button, player), state)
|
||||
end
|
||||
|
||||
-- If visible state is true, then we don't need to check all elements
|
||||
if state then
|
||||
clear_left_flow.visible = true
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if any left elements are visible
|
||||
--- @diagnostic disable-next-line invisible
|
||||
local player_elements = ExpGui._get_player_elements(player)
|
||||
local flow_name = elements.core_button_flow.name
|
||||
for name, left_element in pairs(player_elements.left) do
|
||||
if left_element.visible and name ~= flow_name then
|
||||
clear_left_flow.visible = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- There are no visible left elements, so can hide the button
|
||||
clear_left_flow.visible = false
|
||||
end
|
||||
|
||||
--- @class ExpGui.create_toolbar_button__param: LuaGuiElement.add_param.sprite_button, LuaGuiElement.add_param.button
|
||||
--- @field name string
|
||||
--- @field type nil
|
||||
--- @field left_element ExpElement| nil
|
||||
--- @field visible ExpGui.VisibleCallback | boolean | nil
|
||||
|
||||
--- Create a toolbar button
|
||||
--- @param options ExpGui.create_toolbar_button__param
|
||||
--- @return ExpElement
|
||||
function ExpGui.create_toolbar_button(options)
|
||||
-- Extract the custom options from the element.add options
|
||||
local name = assert(options.name, "Name is required for the element")
|
||||
options.type = options.sprite ~= nil and "sprite-button" or "button"
|
||||
|
||||
local visible = options.visible
|
||||
if visible == nil then visible = true end
|
||||
options.visible = nil
|
||||
|
||||
local auto_toggle = options.auto_toggle
|
||||
options.auto_toggle = nil
|
||||
|
||||
local left_element = options.left_element
|
||||
options.left_element = nil
|
||||
|
||||
if options.style == nil then
|
||||
options.style = toolbar_button_default_style
|
||||
end
|
||||
|
||||
-- Create the new element define
|
||||
local toolbar_button = ExpGui.element(name)
|
||||
:draw(options)
|
||||
:style{
|
||||
minimal_width = toolbar_button_size,
|
||||
height = toolbar_button_size,
|
||||
padding = options.sprite ~= nil and -2 or nil,
|
||||
}
|
||||
|
||||
-- If a left element was given then link the define
|
||||
if left_element then
|
||||
left_elements_with_button[left_element.name] = toolbar_button
|
||||
buttons_with_left_element[toolbar_button.name] = left_element
|
||||
end
|
||||
|
||||
-- Setup auto toggle, required if there is a left element
|
||||
if auto_toggle or left_element then
|
||||
toolbar_button:on_click(function(def, event)
|
||||
local state = ExpGui.set_toolbar_button_style(event.element)
|
||||
if left_element then
|
||||
local player = ExpGui.get_player(event)
|
||||
ExpGui.set_left_element_visible(left_element, player, state)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Add the define to the top flow and return
|
||||
ExpGui.add_top_element(toolbar_button, visible)
|
||||
return toolbar_button
|
||||
end
|
||||
|
||||
--- Update the consistency of the core elements and registered elements
|
||||
--- @param player LuaPlayer
|
||||
--- @param skip_ensure boolean?
|
||||
function ExpGui.apply_consistency_checks(player, skip_ensure)
|
||||
if not skip_ensure then
|
||||
--- @diagnostic disable-next-line invisible
|
||||
ExpGui._ensure_elements{ player_index = player.index }
|
||||
end
|
||||
|
||||
-- Get the core buttons for the player
|
||||
local core_button_data = elements.core_button_flow.data[player]
|
||||
local hide_top_flow = ExpGui.get_top_element(elements.hide_top_flow, player)
|
||||
local show_top_flow = core_button_data.show_top_flow --- @type LuaGuiElement
|
||||
local clear_left_flow = core_button_data.clear_left_flow --- @type LuaGuiElement
|
||||
|
||||
-- Check if any top elements are visible, this includes ones not controlled by this module
|
||||
local has_top_elements = false
|
||||
local top_flow = ExpGui.get_top_flow(player)
|
||||
for _, element in pairs(top_flow.children) do
|
||||
if element.visible and element ~= hide_top_flow then
|
||||
has_top_elements = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- The show button is only visible when the flow isn't visible but does have visible children
|
||||
show_top_flow.visible = has_top_elements and not top_flow.visible or false
|
||||
|
||||
--- @diagnostic disable-next-line invisible
|
||||
local player_elements = ExpGui._get_player_elements(player)
|
||||
local left_elements, top_elements = player_elements.left, player_elements.top
|
||||
|
||||
--- Update the styles of toolbar buttons with left elements
|
||||
for name, top_element in pairs(top_elements) do
|
||||
local left_element = buttons_with_left_element[name]
|
||||
if left_element then
|
||||
local element = assert(left_elements[left_element.name], left_element.name)
|
||||
ExpGui.set_toolbar_button_style(top_element, element.visible)
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if any left elements are visible
|
||||
local flow_name = elements.core_button_flow.name
|
||||
for name, left_element in pairs(left_elements) do
|
||||
if left_element.visible and name ~= flow_name then
|
||||
clear_left_flow.visible = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- There are no visible left elements, so can hide the button
|
||||
clear_left_flow.visible = false
|
||||
end
|
||||
|
||||
--- Hides the top flow when clicked
|
||||
elements.hide_top_flow = ExpGui.element("hide_top_flow")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "exp-gui.hide-top-flow" },
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 36,
|
||||
}
|
||||
:on_click(function(def, event)
|
||||
local player = ExpGui.get_player(event)
|
||||
ExpGui.set_top_flow_visible(player, false)
|
||||
end)
|
||||
|
||||
--- Shows the top flow when clicked
|
||||
elements.show_top_flow = ExpGui.element("show_top_flow")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/preset",
|
||||
style = "tool_button",
|
||||
tooltip = { "exp-gui.show-top-flow" },
|
||||
}
|
||||
:style{
|
||||
padding = -2,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(def, event)
|
||||
local player = ExpGui.get_player(event)
|
||||
ExpGui.set_top_flow_visible(player, true)
|
||||
end)
|
||||
|
||||
--- Hides all left elements when clicked
|
||||
elements.clear_left_flow = ExpGui.element("clear_left_flow")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/close_black",
|
||||
style = "tool_button",
|
||||
tooltip = { "exp-gui.clear-left-flow" },
|
||||
}
|
||||
:style{
|
||||
padding = -3,
|
||||
width = 18,
|
||||
height = 20,
|
||||
}
|
||||
:on_click(function(def, event)
|
||||
local player = ExpGui.get_player(event)
|
||||
event.element.visible = false
|
||||
|
||||
--- @diagnostic disable-next-line invisible
|
||||
local player_elements = ExpGui._get_player_elements(player)
|
||||
local flow_name = elements.core_button_flow.name
|
||||
for name, left_element in pairs(player_elements.left) do
|
||||
if name ~= flow_name then
|
||||
left_element.visible = false
|
||||
local toolbar_button = left_elements_with_button[name]
|
||||
if toolbar_button then
|
||||
ExpGui.set_toolbar_button_style(ExpGui.get_top_element(toolbar_button, player), false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Contains the two buttons on the left flow
|
||||
elements.core_button_flow = ExpGui.element("core_button_flow")
|
||||
:draw(function(def, parent)
|
||||
local flow = parent.add{
|
||||
type = "flow",
|
||||
direction = "vertical",
|
||||
}
|
||||
|
||||
local player = ExpGui.get_player(parent)
|
||||
def.data[player] = {
|
||||
show_top_flow = elements.show_top_flow(flow),
|
||||
clear_left_flow = elements.clear_left_flow(flow),
|
||||
}
|
||||
|
||||
return flow
|
||||
end)
|
||||
|
||||
ExpGui.add_top_element(elements.hide_top_flow, true)
|
||||
ExpGui.add_left_element(elements.core_button_flow, true)
|
||||
|
||||
return elements
|
||||
@@ -56,7 +56,7 @@ local GuiData = {
|
||||
-- This class has no prototype methods
|
||||
-- Do add keys to _raw without also referencing scope_data
|
||||
|
||||
--- @class ExpGui.GuiData: table
|
||||
--- @class ExpGui.GuiData: ExpGui.GuiData_Internal
|
||||
--- @field element_data table<uint, table<uint, any>>
|
||||
--- @field player_data table<uint, any>
|
||||
--- @field force_data table<uint, any>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
[exp-gui]
|
||||
hide-top-flow=Hide Toolbar.
|
||||
show-top-flow=Show Toolbar.
|
||||
clear-left-flow=Hide all open windows.
|
||||
@@ -4,9 +4,11 @@
|
||||
"data.lua",
|
||||
"iter.lua",
|
||||
"prototype.lua",
|
||||
"module_exports.lua"
|
||||
"control.lua"
|
||||
],
|
||||
"require": [
|
||||
"core_elements.lua",
|
||||
"test.lua"
|
||||
],
|
||||
"dependencies": {
|
||||
"clusterio": "*",
|
||||
|
||||
@@ -1,186 +1 @@
|
||||
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
local ExpElement = require("./prototype")
|
||||
|
||||
--- @alias ExpGui.VisibleCallback fun(player: LuaPlayer, element: LuaGuiElement): boolean
|
||||
|
||||
--- @class ExpGui.player_elements
|
||||
--- @field top table<string, LuaGuiElement>
|
||||
--- @field left table<string, LuaGuiElement>
|
||||
--- @field relative table<string, LuaGuiElement>
|
||||
|
||||
--- @type table<uint, ExpGui.player_elements>
|
||||
local player_elements = {}
|
||||
Storage.register(player_elements, function(tbl)
|
||||
player_elements = tbl
|
||||
end)
|
||||
|
||||
--- @class ExpGui
|
||||
local ExpGui = {
|
||||
element = ExpElement,
|
||||
top_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
left_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
relative_elements = {}, --- @type table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
}
|
||||
|
||||
local mod_gui = require("mod-gui")
|
||||
ExpGui.get_top_flow = mod_gui.get_button_flow
|
||||
ExpGui.get_left_flow = mod_gui.get_frame_flow
|
||||
|
||||
--- Get a player from an element or gui event
|
||||
--- @param input LuaGuiElement | { player_index: uint }
|
||||
--- @return LuaPlayer
|
||||
function ExpGui.get_player(input)
|
||||
return assert(game.get_player(input.player_index))
|
||||
end
|
||||
|
||||
--- Toggle the enable state of an element
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
function ExpGui.toggle_enabled_state(element, state)
|
||||
if not element or not element.valid then return end
|
||||
if state == nil then
|
||||
state = not element.enabled
|
||||
end
|
||||
element.enabled = state
|
||||
end
|
||||
|
||||
--- Toggle the visibility of an element
|
||||
--- @param element LuaGuiElement
|
||||
--- @param state boolean?
|
||||
function ExpGui.toggle_visible_state(element, state)
|
||||
if not element or not element.valid then return end
|
||||
if state == nil then
|
||||
state = not element.visible
|
||||
end
|
||||
element.visible = state
|
||||
end
|
||||
|
||||
--- Destroy an element if it exists and is valid
|
||||
--- @param element LuaGuiElement?
|
||||
function ExpGui.destroy_if_valid(element)
|
||||
if not element or not element.valid then return end
|
||||
element.destroy()
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the top flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_top_element(define, visible)
|
||||
assert(ExpGui.top_elements[define.name] == nil, "Element is already added to the top flow")
|
||||
ExpGui.top_elements[define] = visible or false
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_left_element(define, visible)
|
||||
assert(ExpGui.left_elements[define.name] == nil, "Element is already added to the left flow")
|
||||
ExpGui.left_elements[define] = visible or false
|
||||
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param visible ExpGui.VisibleCallback | boolean | nil
|
||||
function ExpGui.add_relative_element(define, visible)
|
||||
assert(ExpGui.relative_elements[define.name] == nil, "Element is already added to the relative flow")
|
||||
ExpGui.relative_elements[define] = visible or false
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the top flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_top_element(define, player)
|
||||
return player_elements[player.index].top[define.name]
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the left flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_left_element(define, player)
|
||||
return player_elements[player.index].left[define.name]
|
||||
end
|
||||
|
||||
--- Register a element define to be drawn to the relative flow on join
|
||||
--- @param define ExpElement
|
||||
--- @param player LuaPlayer
|
||||
--- @return LuaGuiElement
|
||||
function ExpGui.get_relative_element(define, player)
|
||||
return player_elements[player.index].relative[define.name]
|
||||
end
|
||||
|
||||
--- Ensure all the correct elements are visible and exist
|
||||
--- @param player LuaPlayer
|
||||
--- @param element_defines table<ExpElement, ExpGui.VisibleCallback | boolean>
|
||||
--- @param elements LuaGuiElement[]
|
||||
--- @param parent LuaGuiElement
|
||||
local function ensure_elements(player, element_defines, elements, parent)
|
||||
local done = {}
|
||||
for define, visible in pairs(element_defines) do
|
||||
local element = elements[define.name]
|
||||
if not element then
|
||||
element = define(parent)
|
||||
end
|
||||
|
||||
if type(visible) == "function" then
|
||||
visible = visible(player, element)
|
||||
end
|
||||
element.visible = visible
|
||||
done[define.name] = true
|
||||
end
|
||||
|
||||
for name, element in pairs(elements) do
|
||||
if not done[name] then
|
||||
element.destroy()
|
||||
elements[name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Ensure all elements have been created
|
||||
--- @param event EventData.on_player_created | EventData.on_player_joined_game
|
||||
function ExpGui._ensure_elements(event)
|
||||
local player = assert(game.get_player(event.player_index))
|
||||
local elements = player_elements[event.player_index]
|
||||
ensure_elements(player, ExpGui.top_elements, elements.top, player.gui.top)
|
||||
ensure_elements(player, ExpGui.left_elements, elements.left, player.gui.left)
|
||||
ensure_elements(player, ExpGui.relative_elements, elements.relative, player.gui.relative)
|
||||
end
|
||||
|
||||
--- Rerun the visible check for relative elements
|
||||
--- @param event EventData.on_gui_opened
|
||||
local function on_gui_opened(event)
|
||||
local player = ExpGui.get_player(event)
|
||||
local original_element = event.element
|
||||
|
||||
for define, visible in pairs(ExpGui.relative_elements) do
|
||||
local element = ExpGui.get_relative_element(define, player)
|
||||
|
||||
if type(visible) == "function" then
|
||||
visible = visible(player, element)
|
||||
end
|
||||
element.visible = visible
|
||||
|
||||
if visible then
|
||||
event.element = element
|
||||
--- @diagnostic disable-next-line invisible
|
||||
define:_raise_event(event)
|
||||
end
|
||||
end
|
||||
|
||||
event.element = original_element
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
local events = {
|
||||
[e.on_player_created] = ExpGui._ensure_elements,
|
||||
[e.on_player_joined_game] = ExpGui._ensure_elements,
|
||||
[e.on_gui_opened] = on_gui_opened,
|
||||
}
|
||||
|
||||
ExpGui.events = events
|
||||
return ExpGui
|
||||
return require("modules/exp_gui/control")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
|
||||
local GuiData = require("./data")
|
||||
local GuiIter = require("./iter")
|
||||
local GuiData = require("modules/exp_gui/data")
|
||||
local GuiIter = require("modules/exp_gui/iter")
|
||||
|
||||
--- @class ExpGui_ExpElement
|
||||
local ExpElement = {
|
||||
@@ -54,6 +54,12 @@ ExpElement._metatable = {
|
||||
__class = "ExpGui",
|
||||
}
|
||||
|
||||
--- Used to signal that the property should be the same as the define name
|
||||
--- @return function
|
||||
function ExpElement.property_from_name()
|
||||
return ExpElement.property_from_name
|
||||
end
|
||||
|
||||
--- Used to signal that a property should be taken from the arguments
|
||||
--- @param arg_number number?
|
||||
--- @return [function, number?]
|
||||
@@ -64,11 +70,13 @@ end
|
||||
--- Extract the from args properties from a definition
|
||||
--- @param definition table
|
||||
--- @return string[]
|
||||
local function extract_from_args(definition)
|
||||
function ExpElement._prototype:_extract_signals(definition)
|
||||
local from_args = {}
|
||||
for k, v in pairs(definition) do
|
||||
if v == ExpElement.property_from_args then
|
||||
from_args[#from_args + 1] = k
|
||||
elseif v == ExpElement.property_from_name then
|
||||
definition[k] = self.name
|
||||
elseif type(v) == "table" and v[1] == ExpElement.property_from_args then
|
||||
from_args[v[2] or (#from_args + 1)] = k
|
||||
end
|
||||
@@ -81,18 +89,20 @@ end
|
||||
--- @return ExpElement
|
||||
function ExpElement.create(name)
|
||||
ExpUtil.assert_not_runtime()
|
||||
assert(ExpElement._elements[name] == nil, "ExpElement already defined with name: " .. name)
|
||||
local module_name = ExpUtil.get_module_name(2)
|
||||
local element_name = module_name .. "/" .. name
|
||||
assert(ExpElement._elements[element_name] == nil, "ExpElement already defined with name: " .. name)
|
||||
|
||||
local instance = {
|
||||
name = name,
|
||||
data = GuiData.create(name),
|
||||
name = element_name,
|
||||
data = GuiData.create(element_name),
|
||||
_events = {},
|
||||
_debug = {
|
||||
defined_at = ExpUtil.safe_file_path(2),
|
||||
},
|
||||
}
|
||||
|
||||
ExpElement._elements[name] = instance
|
||||
ExpElement._elements[element_name] = instance
|
||||
return setmetatable(instance, ExpElement._metatable)
|
||||
end
|
||||
|
||||
@@ -180,7 +190,7 @@ function ExpElement._prototype:draw(definition)
|
||||
end
|
||||
|
||||
assert(type(definition) == "table", "Definition is not a table or function")
|
||||
local from_args = extract_from_args(definition)
|
||||
local from_args = self:_extract_signals(definition)
|
||||
self._debug.draw_definition = definition
|
||||
|
||||
if #from_args == 0 then
|
||||
@@ -216,7 +226,7 @@ local function definition_factory(prop_name, debug_def, debug_args)
|
||||
end
|
||||
|
||||
assert(type(definition) == "table", "Definition is not a table or function")
|
||||
local from_args = extract_from_args(definition)
|
||||
local from_args = self:_extract_signals(definition)
|
||||
self._debug[debug_def] = definition
|
||||
|
||||
if #from_args == 0 then
|
||||
|
||||
16
exp_gui/module/test.lua
Normal file
16
exp_gui/module/test.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
local ExpGui = require("modules/exp_gui")
|
||||
|
||||
local frame = ExpGui.element("test")
|
||||
:draw{
|
||||
type = "frame",
|
||||
caption = "Hello, World",
|
||||
}
|
||||
|
||||
ExpGui.add_left_element(frame, true)
|
||||
|
||||
ExpGui.create_toolbar_button{
|
||||
name = "test-button",
|
||||
left_element = frame,
|
||||
caption = "Test",
|
||||
}
|
||||
Reference in New Issue
Block a user