Remove legacy gui module

This commit is contained in:
Cooldude2606
2025-01-29 23:05:38 +00:00
parent 824c5fe772
commit 1a88592a8a
13 changed files with 2 additions and 1654 deletions

View File

@@ -1 +0,0 @@
return require("modules.exp_legacy.expcore.gui._require")

View File

@@ -1,144 +0,0 @@
--[[-- Core Module - Gui
- Used to simplify gui creation using factory functions called element defines
@core Gui
@alias Gui
@usage-- To draw your element you only need to call the factory function
-- You are able to pass any other arguments that are used in your custom functions but the first is always the parent element
local example_button_element = example_button(parent_element)
@usage-- Making a factory function for a button with the caption "Example Button"
-- This method has all the same features as LuaGuiElement.add
local example_button =
Gui.element{
type = 'button',
caption = 'Example Button'
}
@usage-- Making a factory function for a button which is contained within a flow
-- This method is for when you still want to register event handlers but cant use the table method
local example_flow_with_button =
Gui.element(function(definition, parent, ...)
-- ... shows that all other arguments from the factory call are passed to this function
-- Here we are adding a flow which we will then later add a button to
local flow =
parent.add{ -- paraent is the element which is passed to the factory function
name = 'example_flow',
type = 'flow'
}
-- Now we add the button to the flow that we created earlier
local element = definition:triggers_event(
flow.add{
type = 'button',
caption = 'Example Button'
}
)
-- You must return a new element, this is so styles can be applied and returned to the caller
-- You may return any of your elements that you added, consider the context in which it will be used for which should be returned
return element
end)
@usage-- Styles can be added to any element define, simplest way mimics LuaGuiElement.style[key] = value
local example_button =
Gui.element{
type = 'button',
caption = 'Example Button',
style = 'forward_button' -- factorio styles can be applied here
}
:style{
height = 25, -- same as element.style.height = 25
width = 100 -- same as element.style.width = 25
}
@usage-- Styles can also have a custom function when the style is dynamic and depends on other factors
-- Use this method if your style is dynamic and depends on other factors
local example_button =
Gui.element{
type = 'button',
caption = 'Example Button',
style = 'forward_button' -- factorio styles can be applied here
}
:style(function(style, element, ...)
-- style is the current style object for the elemenent
-- element is the element that is being changed
-- ... shows that all other arguments from the factory call are passed to this function
local player = game.players[element.player_index]
style.height = 25
style.width = 100
style.font_color = player.color
end)
@usage-- You are able to register event handlers to your elements, these can be factorio events or custom ones
-- All events are checked to be valid before raising any handlers, this means element.valid = true and player.valid = true
Gui.element{
type = 'button',
caption = 'Example Button'
}
:on_click(function(player, element, event)
-- player is the player who interacted with the element to cause the event
-- element is a refrence to the element which caused the event
-- event is a raw refrence to the event data if player and element are not enough
player.print('Clicked: '..element.name)
end)
@usage-- Example from core_defines, Gui.core_defines.hide_left_flow, called like: hide_left_flow(parent_element)
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
-- @element hide_left_flow
local hide_left_flow =
Gui.element{
type = 'sprite-button',
sprite = 'utility/close_black',
style = 'tool_button',
tooltip = {'expcore-gui.left-button-tooltip'}
}
:style{
padding = -3,
width = 18,
height = 20
}
:on_click(function(player, _,_)
Gui.hide_left_flow(player)
end)
@usage-- Eample from defines, Gui.alignment, called like: Gui.alignment(parent, name, horizontal_align, vertical_align)
-- Notice how _ are used to blank arguments that are not needed in that context and how they line up with above
Gui.alignment =
Gui.element(function(_, parent, name, _,_)
return parent.add{
name = name or 'alignment',
type = 'flow',
}
end)
:style(function(style, _,_, horizontal_align, vertical_align)
style.padding = {1, 2}
style.vertical_align = vertical_align or 'center'
style.horizontal_align = horizontal_align or 'right'
style.vertically_stretchable = style.vertical_align ~= 'center'
style.horizontally_stretchable = style.horizontal_align ~= 'center'
end)
]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
require("modules.exp_legacy.expcore.gui.helper_functions")
require("modules.exp_legacy.expcore.gui.core_defines")
require("modules.exp_legacy.expcore.gui.top_flow")
require("modules.exp_legacy.expcore.gui.left_flow")
require("modules.exp_legacy.expcore.gui.defines")
local Roles = ExpUtil.optional_require("modules.exp_legacy.expcore.roles")
local Event = ExpUtil.optional_require("modules/exp_legacy/utils/event")
if Roles and Event then
Event.add(Roles.events.on_role_assigned, function(e)
Gui.update_top_flow(game.players[e.player_index])
end)
Event.add(Roles.events.on_role_unassigned, function(e)
Gui.update_top_flow(game.players[e.player_index])
end)
end
return Gui

View File

@@ -1,89 +0,0 @@
--[[-- Core Module - Gui
- Gui defines that are used internally by the gui system
@module Gui
]]
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
local Event = require("modules/exp_legacy/utils/event")
--- Core Defines.
-- @section coreDefines
--- Button which toggles the top flow elements, version which shows inside the top flow when top flow is visible
-- @element hide_top_flow
local hide_top_flow =
Gui.element{
type = "sprite-button",
sprite = "utility/preset",
style = "tool_button",
tooltip = { "gui_util.button_tooltip" },
name = Gui.unique_static_name,
}
:style{
padding = -2,
width = 18,
height = 36,
}
:on_click(function(player, _, _)
Gui.toggle_top_flow(player, false)
end)
Gui.core_defines.hide_top_flow = hide_top_flow
--- Button which toggles the top flow elements, version which shows inside the left flow when top flow is hidden
-- @element show_top_flow
local show_top_flow =
Gui.element{
type = "sprite-button",
sprite = "utility/preset",
style = "tool_button",
tooltip = { "gui_util.button_tooltip" },
name = Gui.unique_static_name,
}
:style{
padding = -2,
width = 18,
height = 20,
}
:on_click(function(player, _, _)
Gui.toggle_top_flow(player, true)
end)
Gui.core_defines.show_top_flow = show_top_flow
--- Button which hides the elements in the left flow, shows inside the left flow when frames are visible
-- @element hide_left_flow
local hide_left_flow =
Gui.element{
type = "sprite-button",
sprite = "utility/close_black",
style = "tool_button",
tooltip = { "expcore-gui.left-button-tooltip" },
name = Gui.unique_static_name,
}
:style{
padding = -3,
width = 18,
height = 20,
}
:on_click(function(player, _, _)
Gui.hide_left_flow(player)
end)
Gui.core_defines.hide_left_flow = hide_left_flow
--- Draw the core elements when a player joins the game
Event.add(defines.events.on_player_created, function(event)
local player = game.players[event.player_index]
-- Draw the top flow
local top_flow = Gui.get_top_flow(player)
hide_top_flow(top_flow)
Gui.update_top_flow(player)
-- Draw the left flow
local left_flow = Gui.get_left_flow(player)
local button_flow = left_flow.add{ type = "flow", name = "gui_core_buttons", direction = "vertical" }
local show_top = show_top_flow(button_flow)
local hide_left = hide_left_flow(button_flow)
show_top.visible = false
hide_left.visible = false
Gui.draw_left_flow(player)
end)

View File

@@ -1,301 +0,0 @@
--[[-- Core Module - Gui
- Common defines that are used by other modules, non of these are used internally
@module Gui
]]
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
--- Defines.
-- @section defines
--[[-- Draw a flow used to align its child elements, default is right align
@element Gui.alignment
@tparam LuaGuiElement parent the parent element to which the alignment will be added
@tparam[opt='alignment'] string name the name of the alignment flow which is added
@tparam[opt='right'] string horizontal_align the horizontal alignment of the elements in the flow
@tparam[opt='center'] string vertical_align the vertical alignment of the elements in the flow
@treturn LuaGuiElement the alignment flow that was created
@usage-- Adding a right align flow
local alignment = Gui.alignment(element, 'example_right_alignment')
@usage-- Adding a horizontal center and top align flow
local alignment = Gui.alignment(element, 'example_center_top_alignment', 'center', 'top')
]]
Gui.alignment =
Gui.element(function(_, parent, name, _, _)
return parent.add{
name = name or "alignment",
type = "flow",
}
end)
:style(function(style, _, _, horizontal_align, vertical_align)
style.padding = { 1, 2 }
style.vertical_align = vertical_align or "center"
style.horizontal_align = horizontal_align or "right"
style.vertically_stretchable = style.vertical_align ~= "center"
style.horizontally_stretchable = style.horizontal_align ~= "center"
end)
--[[-- Draw a scroll pane that has a table inside of it
@element Gui.scroll_table
@tparam LuaGuiElement parent the parent element to which the scroll table will be added
@tparam number height the maximum height for the scroll pane
@tparam number column_count the number of columns that the table will have
@tparam[opt='scroll'] string name the name of the scroll pane that is added, the table is always called "table"
@treturn LuaGuiElement the table that was created
@usage-- Adding a scroll table with max height of 200 and column count of 3
local scroll_table = Gui.scroll_table(element, 200, 3)
]]
Gui.scroll_table =
Gui.element(function(_, parent, height, column_count, name)
-- Draw the scroll
local scroll_pane =
parent.add{
name = name or "scroll",
type = "scroll-pane",
direction = "vertical",
horizontal_scroll_policy = "never",
vertical_scroll_policy = "auto",
style = "scroll_pane_under_subheader",
}
-- Set the style of the scroll pane
local scroll_style = scroll_pane.style
scroll_style.padding = { 1, 3 }
scroll_style.maximal_height = height
scroll_style.horizontally_stretchable = true
-- Draw the table
local scroll_table =
scroll_pane.add{
type = "table",
name = "table",
column_count = column_count,
}
-- Return the scroll table
return scroll_table
end)
:style{
padding = 0,
cell_padding = 0,
vertical_align = "center",
horizontally_stretchable = true,
}
--[[-- Used to add a frame with the header style, has the option for a right alignment flow for buttons
@element Gui.header
@tparam LuaGuiElement parent the parent element to which the header will be added
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the header
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the header
@tparam[opt=false] boolean add_alignment when true an alignment flow will be added to the header
@tparam[opt='header'] string name the name of the header that is being added, the alignment is always called "alignment"
@treturn LuaGuiElement either the header or the header alignment if add_alignment is true
@usage-- Adding a custom header with a label
local header = Gui.header(
element,
'Example Caption',
'Example Tooltip'
)
]]
Gui.header =
Gui.element(function(_, parent, caption, tooltip, add_alignment, name, label_name)
-- Draw the header
local header =
parent.add{
name = name or "header",
type = "frame",
style = "subheader_frame",
}
-- Change the style of the header
local style = header.style
style.padding = { 2, 4 }
style.use_header_filler = false
style.horizontally_stretchable = true
-- Draw the caption label
if caption then
header.add{
name = label_name or "header_label",
type = "label",
style = "frame_title",
caption = caption,
tooltip = tooltip,
}
end
-- Return either the header or the added alignment
return add_alignment and Gui.alignment(header) or header
end)
--[[-- Used to add a frame with the footer style, has the option for a right alignment flow for buttons
@element Gui.footer
@tparam LuaGuiElement parent the parent element to which the footer will be added
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the footer
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the footer
@tparam[opt=false] boolean add_alignment when true an alignment flow will be added to the footer
@tparam[opt='footer'] string name the name of the footer that is being added, the alignment is always called "alignment"
@treturn LuaGuiElement either the footer or the footer alignment if add_alignment is true
@usage-- Adding a custom footer with a label
local footer = Gui.footer(
element,
'Example Caption',
'Example Tooltip'
)
]]
Gui.footer =
Gui.element(function(_, parent, caption, tooltip, add_alignment, name)
-- Draw the header
local footer =
parent.add{
name = name or "footer",
type = "frame",
style = "subfooter_frame",
}
-- Change the style of the footer
local style = footer.style
style.padding = { 2, 4 }
style.use_header_filler = false
style.horizontally_stretchable = true
-- Draw the caption label
if caption then
footer.add{
name = "footer_label",
type = "label",
style = "frame_title",
caption = caption,
tooltip = tooltip,
}
end
-- Return either the footer or the added alignment
return add_alignment and Gui.alignment(footer) or footer
end)
--[[-- Used for left frames to give them a nice boarder
@element Gui.container
@tparam LuaGuiElement parent the parent element to which the container will be added
@tparam string name the name that you want to give to the outer frame, often just event_trigger
@tparam number width the minimal width that the frame will have
@usage-- Adding a container as a base
local container = Gui.container(parent, 'my_container', 200)
]]
Gui.container =
Gui.element(function(_, parent, name, _)
-- Draw the external container
local frame =
parent.add{
name = name,
type = "frame",
}
frame.style.horizontally_stretchable = false
-- Return the container
return frame.add{
name = "container",
type = "frame",
direction = "vertical",
style = "inside_shallow_frame_packed",
}
end)
:style(function(style, element, _, width)
style.vertically_stretchable = false
local frame_style = element.parent.style
frame_style.padding = 2
frame_style.minimal_width = width
end)
--[[-- Used to make a solid white bar in a gui
@element Gui.bar
@tparam LuaGuiElement parent the parent element to which the bar will be added
@tparam number width the width of the bar that will be made, if not given bar will strech to fill the parent
@usage-- Adding a bar to a gui
local bar = Gui.bar(parent, 100)
]]
Gui.bar =
Gui.element(function(_, parent)
return parent.add{
type = "progressbar",
size = 1,
value = 1,
}
end)
:style(function(style, _, width)
style.height = 3
style.color = { r = 255, g = 255, b = 255 }
if width then
style.width = width
else
style.horizontally_stretchable = true
end
end)
--[[-- Used to make a label which is centered and of a certian size
@element Gui.centered_label
@tparam LuaGuiElement parent the parent element to which the label will be added
@tparam number width the width of the label, must be given in order to center the caption
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the label
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the label
@usage-- Adding a centered label
local label = Gui.centered_label(parent, 100, 'This is centered')
]]
Gui.centered_label =
Gui.element(function(_, parent, width, caption, tooltip)
local label = parent.add{
type = "label",
caption = caption,
tooltip = tooltip,
}
local style = label.style
style.horizontal_align = "center"
style.single_line = false
style.width = width
return label
end)
--[[-- Used to make a title which has two bars on either side
@element Gui.title_label
@tparam LuaGuiElement parent the parent element to which the label will be added
@tparam number width the width of the first bar, this can be used to position the label
@tparam ?string|Concepts.LocalizedString caption the caption that will be shown on the label
@tparam[opt] ?string|Concepts.LocalizedString tooltip the tooltip that will be shown on the label
@usage-- Adding a centered label
local label = Gui.centered_label(parent, 100, 'This is centered')
]]
Gui.title_label =
Gui.element(function(_, parent, width, caption, tooltip)
local title_flow = parent.add{ type = "flow" }
title_flow.style.vertical_align = "center"
Gui.bar(title_flow, width)
local title_label = title_flow.add{
type = "label",
caption = caption,
tooltip = tooltip,
style = "frame_title",
}
Gui.bar(title_flow)
return title_label
end)

View File

@@ -1,91 +0,0 @@
--[[-- Core Module - Gui
- Functions used to help with the use of guis
@module Gui
]]
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
--- Helper Functions.
-- @section helperFunctions
--[[-- Get the player that owns a gui element
@tparam LuaGuiElement element the element to get the owner of
@treturn LuaPlayer the player that owns this element
@usage-- Geting the owner of an element
local player = Gui.get_player_from_element(element)
]]
function Gui.get_player_from_element(element)
if not element or not element.valid then return end
return game.players[element.player_index]
end
--[[-- Will toggle the enabled state of an element or set it to the one given
@tparam LuaGuiElement element the element to toggle/set the enabled state of
@tparam[opt] boolean state with given will set the state, else state will be toggled
@treturn boolean the new enabled state that the element has
@usage-- Toggling the the enabled state
local new_enabled_state = Gui.toggle_enabled_state(element)
]]
function Gui.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
return state
end
--[[-- Will toggle the visible state of an element or set it to the one given
@tparam LuaGuiElement element the element to toggle/set the visible state of
@tparam[opt] boolean state with given will set the state, else state will be toggled
@treturn boolean the new visible state that the element has
@usage-- Toggling the the visible state
local new_visible_state = Gui.toggle_visible_state(element)
]]
function Gui.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
return state
end
--[[-- Destory a gui element without causing any errors, often because the element was already removed
@tparam LuaGuiElement element the element that you want to remove
@treturn boolean true if the element was valid and has been removed
@usage-- Remove a child element if it exists
Gui.destroy_if_valid(element[child_name])
]]
function Gui.destroy_if_valid(element)
if not element or not element.valid then return false end
element.destroy()
return true
end
--[[-- Returns a table to be used as the style for a sprite buttons, produces a sqaure button
@tparam number size the size that you want the button to be
@tparam[opt=-2] number padding the padding that you want on the sprite
@tparam[opt] table style any extra style settings that you want to have
@treturn table the style table to be used with element_define:style()
@usage-- Adding a sprite button with size 20
local button =
Gui.element{
type = 'sprite-button',
sprite = 'entity/inserter'
}
:style(Gui.sprite_style(20))
]]
function Gui.sprite_style(size, padding, style)
style = style or {}
style.padding = padding or -2
style.height = size
style.width = size
return style
end

View File

@@ -1,277 +0,0 @@
--[[-- Core Module - Gui
- Used to define new gui elements and gui event handlers
@module Gui
]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
local mod_gui = require "mod-gui"
local hide_left_flow = Gui.core_defines.hide_left_flow.name
--- Left Flow.
-- @section leftFlow
-- Triggered when a user changed the visibility of a left flow element by clicking a button
Gui.events.on_visibility_changed_by_click = "on_visibility_changed_by_click"
--- Contains the uids of the elements that will shown on the left flow and their join functions
-- @table left_elements
Gui.left_elements = {}
--[[-- Gets the flow refered to as the left flow, each player has one left flow
@function Gui.get_left_flow(player)
@tparam LuaPlayer player the player that you want to get the left flow for
@treturn LuaGuiElement the left element flow
@usage-- Geting your left flow
local left_flow = Gui.get_left_flow(game.player)
]]
Gui.get_left_flow = mod_gui.get_frame_flow
--[[-- Sets an element define to be drawn to the left flow when a player joins, includes optional check
@tparam[opt] ?boolean|function open_on_join called during first darw to decide if the element should be visible
@treturn table the new element define that is used to register events to this element
@usage-- Adding the example button
example_flow_with_button:add_to_left_flow(true)
]]
function Gui._prototype_element:add_to_left_flow(open_on_join)
ExpUtil.assert_not_runtime()
if not self.name then error("Elements for the top flow must have a static name") end
self.open_on_join = open_on_join or false
table.insert(Gui.left_elements, self)
return self
end
--[[-- Creates a button on the top flow which will toggle the given element define, the define must exist in the left flow
@tparam string sprite the sprite that you want to use on the button
@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have
@tparam table element_define the element define that you want to have toggled by this button, define must exist on the left flow
@tparam[opt] function authenticator used to decide if the button should be visible to a player
@usage-- Add a button to toggle a left element
local toolbar_button =
Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', example_flow_with_button, function(player)
return player.admin
end)
]]
function Gui.left_toolbar_button(sprite, tooltip, element_define, authenticator)
local button = Gui.toolbar_button(sprite, tooltip, authenticator)
-- Add on_click handler to handle click events comming from the player
button:on_click(function(player, _, _)
-- Raise custom event that tells listening elements if the element has changed visibility by a player clicking
-- Used in warp gui to handle the keep open logic
button:raise_event{
name = Gui.events.on_visibility_changed_by_click,
element = Gui.get_top_element(player, button),
state = Gui.toggle_left_element(player, element_define),
}
end)
-- Add property to the left flow element with the name of the button
-- This is for the ability to reverse lookup the button from the left flow element
element_define.toolbar_button = button
button.left_flow_element = element_define
return button
end
Gui._left_flow_order_src = "<default>"
--- Get the order of elements in the left flow, first argument is player but is unused in the default method
function Gui.get_left_flow_order(_)
return Gui.left_elements
end
--- Inject a custom left flow order provider, this should accept a player and return a list of elements definitions to draw
function Gui.inject_left_flow_order(provider)
Gui.get_left_flow_order = provider
local debug_info = debug.getinfo(2, "Sn")
local file_name = debug_info.short_src:sub(10, -5)
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
Gui._left_flow_order_src = file_name .. ":" .. func_name
end
--[[-- Draw all the left elements onto the left flow, internal use only with on join
@tparam LuaPlayer player the player that you want to draw the elements for
@usage-- Draw all the left elements
Gui.draw_left_flow(player)
]]
function Gui.draw_left_flow(player)
local left_flow = Gui.get_left_flow(player)
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
local show_hide_button = false
-- Get the order to draw the elements in
local flow_order = Gui.get_left_flow_order(player)
if #flow_order ~= #Gui.left_elements then
error(string.format("Left flow order provider (%s) did not return the correct element count, expect %d got %d",
Gui._left_flow_order_src, #Gui.left_elements, #flow_order
))
end
for _, element_define in ipairs(flow_order) do
-- Draw the element to the left flow
local draw_success, left_element = xpcall(function()
return element_define(left_flow)
end, debug.traceback)
if not draw_success then
log("There as been an error with an element draw function: " .. element_define.defined_at .. "\n\t" .. left_element)
goto continue
end
-- Check if it should be open by default
local open_on_join = element_define.open_on_join
local visible = type(open_on_join) == "boolean" and open_on_join or false
if type(open_on_join) == "function" then
local success, err = xpcall(open_on_join, debug.traceback, player)
if not success then
log("There as been an error with an open on join hander for a gui element:\n\t" .. err)
goto continue
end
visible = err
end
-- Set the visible state of the element
left_element.visible = visible
show_hide_button = show_hide_button or visible
-- Check if the the element has a button attached
if element_define.toolbar_button then
Gui.toggle_toolbar_button(player, element_define.toolbar_button, visible)
end
::continue::
end
hide_button.visible = show_hide_button
end
--- Reorder the left flow elements to match that returned by the provider, uses a method equivalent to insert sort
function Gui.reorder_left_flow(player)
local left_flow = Gui.get_left_flow(player)
-- Get the order to draw the elements in
local flow_order = Gui.get_left_flow_order(player)
if #flow_order ~= #Gui.left_elements then
error(string.format("Left flow order provider (%s) did not return the correct element count, expect %d got %d",
Gui._left_flow_order_src, #Gui.left_elements, #flow_order
))
end
-- Reorder the elements, index 1 is the core ui buttons so +1 is required
for index, element_define in ipairs(flow_order) do
local element = left_flow[element_define.name]
left_flow.swap_children(index + 1, element.get_index_in_parent())
end
end
--[[-- Update the visible state of the hide button, can be used to check if any frames are visible
@tparam LuaPlayer player the player to update the left flow for
@treturn boolean true if any left element is visible
@usage-- Check if any left elements are visible
local visible = Gui.update_left_flow(player)
]]
function Gui.update_left_flow(player)
local left_flow = Gui.get_left_flow(player)
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
for _, element_define in ipairs(Gui.left_elements) do
local left_element = left_flow[element_define.name]
if left_element.visible then
hide_button.visible = true
return true
end
end
hide_button.visible = false
return false
end
--[[-- Hides all left elements for a player
@tparam LuaPlayer player the player to hide the elements for
@usage-- Hide your left elements
Gui.hide_left_flow(game.player)
]]
function Gui.hide_left_flow(player)
local top_flow = Gui.get_top_flow(player)
local left_flow = Gui.get_left_flow(player)
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
-- Set the visible state of all elements in the flow
hide_button.visible = false
for _, element_define in ipairs(Gui.left_elements) do
left_flow[element_define.name].visible = false
-- Check if the the element has a toobar button attached
if element_define.toolbar_button then
-- Check if the topflow contains the button
local button = top_flow[element_define.toolbar_button.name]
if button then
-- Style the button
Gui.toggle_toolbar_button(player, element_define.toolbar_button, false)
-- Raise the custom event if all of the top checks have passed
element_define.toolbar_button:raise_event{
name = Gui.events.on_visibility_changed_by_click,
element = button,
state = false,
}
end
end
end
end
--- Checks if an element is loaded, used internally when the normal left gui assumptions may not hold
function Gui.left_flow_loaded(player, element_define)
local left_flow = Gui.get_left_flow(player)
return left_flow[element_define.name] ~= nil
end
--[[-- Get the element define that is in the left flow, use in events without an element refrence
@tparam LuaPlayer player the player that you want to get the element for
@tparam table element_define the element that you want to get
@treturn LuaGuiElement the gui element linked to this define for this player
@usage-- Get your left element
local frame = Gui.get_left_element(game.player, example_flow_with_button)
]]
function Gui.get_left_element(player, element_define)
local left_flow = Gui.get_left_flow(player)
return assert(left_flow[element_define.name], "Left element failed to load")
end
--[[-- Toggles the visible state of a left element for a given player, can be used to set the visible state
@tparam LuaPlayer player the player that you want to toggle the element for
@tparam table element_define the element that you want to toggle
@tparam[opt] boolean state with given will set the state, else state will be toggled
@treturn boolean the new visible state of the element
@usage-- Toggle your example button
Gui.toggle_top_flow(game.player, example_flow_with_button)
@usage-- Show your example button
Gui.toggle_top_flow(game.player, example_flow_with_button, true)
]]
function Gui.toggle_left_element(player, element_define, state)
-- Set the visible state
local element = Gui.get_left_element(player, element_define)
if state == nil then state = not element.visible end
element.visible = state
Gui.update_left_flow(player)
-- Check if the the element has a button attached
if element_define.toolbar_button then
Gui.toggle_toolbar_button(player, element_define.toolbar_button, state)
end
return state
end

View File

@@ -1,415 +0,0 @@
--[[-- Core Module - Gui
- Used to simplify gui creation using factory functions called element defines
@module Gui
]]
local ExpUtil = require("modules/exp_util")
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
local Gui = {
--- The current highest uid that is being used by a define, will not increase during runtime
uid = 0,
--- Used to automatically assign a unique static name to an element
unique_static_name = {},
--- String indexed table used to avoid conflict with custom event names, similar to how defines.events works
events = {},
--- Uid indexed array that stores all the factory functions that were defined, no new values will be added during runtime
defines = {},
--- An string indexed table of all the defines which are used by the core of the gui system, used for internal reference
core_defines = {},
--- Used to store the file names where elements were defined, this can be useful to find the uid of an element, mostly for debugging
file_paths = {},
--- Used to store extra information about elements as they get defined such as the params used and event handlers registered to them
debug_info = {},
--- The prototype used to store the functions of an element define
_prototype_element = {},
--- The prototype metatable applied to new element defines
_mt_element = {},
}
--- Allow access to the element prototype methods
Gui._mt_element.__index = Gui._prototype_element
--- Allows the define to be called to draw the element
function Gui._mt_element.__call(self, parent, ...)
local element, no_events = self._draw(self, parent, ...)
if self._style then self._style(element.style, element, ...) end
-- Asserts to catch common errors
if element then
if self.name and self.name ~= element.name then
error("Static name \"" .. self.name .. "\" expected but got: " .. tostring(element.name))
end
local event_triggers = element.tags and element.tags.ExpGui_event_triggers
if event_triggers and table.array_contains(event_triggers, self.uid) then
error("Element::triggers_events should not be called on the value you return from the definition")
end
elseif self.name then
error("Static name \"" .. self.name .. "\" expected but no element was returned from the definition")
end
-- Register events by default, but allow skipping them
if no_events == self.no_events then
return element
else
return element and self:triggers_events(element)
end
end
--- Get where a function was defined as a string
local function get_defined_at(level)
local debug_info = debug.getinfo(level, "Sn")
local file_name = debug_info.short_src:sub(10, -5)
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
return file_name .. ":" .. func_name
end
--- Element Define.
-- @section elementDefine
--[[-- Used to define new elements for your gui, can be used like LuaGuiElement.add or a custom function
@tparam ?table|function element_define the define information for the gui element, same data as LuaGuiElement.add, or a custom function may be used
@treturn table the new element define, this can be considered a factory for the element which can be called to draw the element to any other element
@usage-- Using element defines like LuaGuiElement.add
-- This returns a factory function to draw a button with the caption "Example Button"
local example_button =
Gui.element{
type = 'button',
caption = 'Example Button'
}
@usage-- Using element defines with a custom factory function
-- This method can be used if you still want to be able register event handlers but it is too complex to be compatible with LuaGuiElement.add
local example_flow_with_button =
Gui.element(function(event_trigger, parent, ...)
-- ... shows that all other arguments from the factory call are passed to this function
-- parent is the element which was passed to the factory function where you should add your new element
-- here we are adding a flow which we will then later add a button to
local flow =
parent.add{
name = 'example_flow',
type = 'flow'
}
-- event_trigger should be the name of any elements you want to trigger your event handlers, such as on_click or on_state_changed
-- now we add the button to the flow that we created earlier
local element =
flow.add{
name = event_trigger,
type = 'button',
caption = 'Example Button'
}
-- you must return your new element, this is so styles can be applied and returned to the caller
-- you may return any of your elements that you add, consider the context in which it will be used for what should be returned
return element
end)
]]
function Gui.element(element_define)
ExpUtil.assert_not_runtime()
-- Set the metatable to allow access to register events
local element = setmetatable({}, Gui._mt_element)
-- Increment the uid counter
local uid = Gui.uid + 1
Gui.uid = uid
element.uid = uid
Gui.debug_info[uid] = { draw = "None", style = "None", events = {} }
-- Add the definition function
if type(element_define) == "table" then
Gui.debug_info[uid].draw = element_define
if element_define.name == Gui.unique_static_name then
element_define.name = "ExpGui_" .. tostring(uid)
end
for k, v in pairs(element_define) do
if element[k] == nil then
element[k] = v
end
end
element._draw = function(_, parent)
return parent.add(element_define)
end
else
Gui.debug_info[uid].draw = get_defined_at(element_define)
element._draw = element_define
end
-- Add the define to the base module
element.defined_at = get_defined_at(3)
Gui.file_paths[uid] = element.defined_at
Gui.defines[uid] = element
-- Return the element so event handers can be accessed
return element
end
--[[-- Used to extent your element define with a style factory, this style will be applied to your element when created, can also be a custom function
@tparam ?table|function style_define style table where each key and value pair is treated like LuaGuiElement.style[key] = value, a custom function can be used
@treturn table the element define is returned to allow for event handlers to be registered
@usage-- Using the table method of setting the style
local example_button =
Gui.element{
type = 'button',
caption = 'Example Button',
style = 'forward_button' -- factorio styles can be applied here
}
:style{
height = 25, -- same as element.style.height = 25
width = 100 -- same as element.style.width = 25
}
@usage-- Using the function method to set the style
-- Use this method if your style is dynamic and depends on other factors
local example_button =
Gui.element{
type = 'button',
caption = 'Example Button',
style = 'forward_button' -- factorio styles can be applied here
}
:style(function(style, element, ...)
-- style is the current style object for the elemenent
-- element is the element that is being changed
-- ... shows that all other arguments from the factory call are passed to this function
local player = game.players[element.player_index]
style.height = 25
style.width = 100
style.font_color = player.color
end)
]]
function Gui._prototype_element:style(style_define)
ExpUtil.assert_not_runtime()
-- Add the definition function
if type(style_define) == "table" then
Gui.debug_info[self.uid].style = style_define
self._style = function(style)
for key, value in pairs(style_define) do
style[key] = value
end
end
else
Gui.debug_info[self.uid].style = get_defined_at(style_define)
self._style = style_define
end
-- Return the element so event handers can be accessed
return self
end
--[[-- Enforce the fact the element has a static name, this is required for the cases when a function define is used
@tparam[opt] string element The element that will trigger calls to the event handlers
@treturn table the element define is returned to allow for event handlers to be registered
]]
function Gui._prototype_element:static_name(name)
ExpUtil.assert_not_runtime()
if name == Gui.unique_static_name then
self.name = "ExpGui_" .. tostring(self.uid)
else
self.name = name
end
return self
end
--[[-- Used to link an element to an element define such that any event on the element will call the handlers on the element define
-- You should not call this on the element you return from your constructor because this is done automatically
@tparam LuaGuiElement element The element that will trigger calls to the event handlers
@treturn LuaGuiElement The element passed as the argument to allow for cleaner returns
]]
function Gui._prototype_element:triggers_events(element)
if not self._has_events then return element end
local tags = element.tags
if not tags then
element.tags = { ExpGui_event_triggers = { self.uid } }
return element
elseif not tags.ExpGui_event_triggers then
--- @diagnostic disable-next-line: name-style-check
tags.ExpGui_event_triggers = { self.uid }
elseif table.array_contains(tags.ExpGui_event_triggers, self.uid) then
error("Element::triggers_events called multiple times on the same element with the same definition")
else
table.insert(tags.ExpGui_event_triggers, self.uid)
end
-- To modify a set of tags, the whole table needs to be written back to the respective property.
element.tags = tags
return element
end
--- Explicitly skip events on the element returned by your definition function
function Gui._prototype_element:no_events(element)
return element, self.no_events
end
--[[-- Set the handler which will be called for a custom event, only one handler can be used per event per element
@tparam string event_name the name of the event you want to handler to be called on, often from Gui.events
@tparam function handler the handler that you want to be called when the event is raised
@treturn table the element define so more handleres can be registered
@usage-- Register a handler to "my_custom_event" for this element
element_deinfe:on_event('my_custom_event', function(event)
event.player.print(player.name)
end)
]]
function Gui._prototype_element:on_event(event_name, handler)
ExpUtil.assert_not_runtime()
table.insert(Gui.debug_info[self.uid].events, event_name)
Gui.events[event_name] = event_name
self[event_name] = handler
self._has_events = true
return self
end
--[[-- Raise the handler which is attached to an event; external use should be limited to custom events
@tparam table event the event table passed to the handler, must contain fields: name, element
@treturn table the element define so more events can be raised
@usage Raising a custom event
element_define:raise_event{
name = 'my_custom_event',
element = element
}
]]
function Gui._prototype_element:raise_event(event)
-- Check the element is valid
local element = event.element
if not element or not element.valid then
return self
end
-- Get the event handler for this element
local handler = self[event.name]
if not handler then
return self
end
-- Get the player for this event
local player_index = event.player_index or element.player_index
local player = game.players[player_index]
if not player or not player.valid then
return self
end
event.player = player
local success, err = xpcall(handler, debug.traceback, player, element, event)
if not success then
error("There as been an error with an event handler for a gui element:\n\t" .. err)
end
return self
end
-- This function is used to link element define events and the events from the factorio api
local function event_handler_factory(event_name)
Event.add(event_name, function(event)
local element = event.element
if not element or not element.valid then return end
local event_triggers = element.tags.ExpGui_event_triggers
if not event_triggers then return end
for _, uid in pairs(event_triggers) do
local element_define = Gui.defines[uid]
if element_define then
element_define:raise_event(event)
end
end
end)
Gui.events[event_name] = event_name
return function(self, handler)
return self:on_event(event_name, handler)
end
end
--- Element Events.
-- @section elementEvents
--- Called when the player opens a GUI.
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_open(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_open = event_handler_factory(defines.events.on_gui_opened)
--- Called when the player closes the GUI they have open.
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_close(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_close = event_handler_factory(defines.events.on_gui_closed)
--- Called when LuaGuiElement is clicked.
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_click(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_click = event_handler_factory(defines.events.on_gui_click)
--- Called when a LuaGuiElement is confirmed, for example by pressing Enter in a textfield.
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_confirmed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_confirmed = event_handler_factory(defines.events.on_gui_confirmed)
--- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_checked_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_checked_changed = event_handler_factory(defines.events.on_gui_checked_state_changed)
--- Called when LuaGuiElement element value is changed (related to choose element buttons).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_elem_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_elem_changed = event_handler_factory(defines.events.on_gui_elem_changed)
--- Called when LuaGuiElement element location is changed (related to frames in player.gui.screen).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_location_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_location_changed = event_handler_factory(defines.events.on_gui_location_changed)
--- Called when LuaGuiElement selected tab is changed (related to tabbed-panes).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_tab_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_tab_changed = event_handler_factory(defines.events.on_gui_selected_tab_changed)
--- Called when LuaGuiElement selection state is changed (related to drop-downs and listboxes).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_selection_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_selection_changed = event_handler_factory(defines.events.on_gui_selection_state_changed)
--- Called when LuaGuiElement switch state is changed (related to switches).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_switch_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_switch_changed = event_handler_factory(defines.events.on_gui_switch_state_changed)
--- Called when LuaGuiElement text is changed by the player.
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_text_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_text_changed = event_handler_factory(defines.events.on_gui_text_changed)
--- Called when LuaGuiElement slider value is changed (related to the slider element).
-- @tparam function handler the event handler which will be called
-- @usage element_define:on_value_changed(function(event)
-- event.player.print(table.inspect(event))
-- end)
Gui._prototype_element.on_value_changed = event_handler_factory(defines.events.on_gui_value_changed)
-- Module return
return Gui

View File

@@ -1,316 +0,0 @@
--[[-- Core Module - Gui
- Controls the elements on the top flow
@module Gui
]]
local ExpUtil = require("modules/exp_util")
local Gui = require("modules.exp_legacy.expcore.gui.prototype")
local mod_gui = require "mod-gui" --- @dep mod-gui
local toolbar_button_size = 36
local hide_top_flow = Gui.core_defines.hide_top_flow.name
local show_top_flow = Gui.core_defines.show_top_flow.name
--- Top Flow.
-- @section topFlow
-- Triggered when a user changed the visibility of a left flow element by clicking a button
Gui.events.on_toolbar_button_toggled = "on_toolbar_button_toggled"
--- Contains the uids of the elements that will shown on the top flow and their auth functions
-- @table top_elements
Gui.top_elements = {}
--- The style that should be used for buttons on the top flow
-- @field Gui.top_flow_button_style
Gui.top_flow_button_style = mod_gui.button_style
--- The style that should be used for buttons on the top flow when their flow is visible
-- @field Gui.top_flow_button_toggled_style
Gui.top_flow_button_toggled_style = "menu_button_continue"
--[[-- Styles a top flow button depending on the state given
@tparam LuaGuiElement button the button element to style
@tparam boolean state The state the button is in
@usage-- Sets the button to the visible style
Gui.toolbar_button_style(button, true)
@usage-- Sets the button to the hidden style
Gui.toolbar_button_style(button, false)
]]
function Gui.toolbar_button_style(button, state, size)
--- @cast button LuaGuiElement
if state then
button.style = Gui.top_flow_button_toggled_style
else
button.style = Gui.top_flow_button_style
end
button.style.minimal_width = size or toolbar_button_size
button.style.height = size or toolbar_button_size
button.style.padding = -2
end
--[[-- Gets the flow refered to as the top flow, each player has one top flow
@function Gui.get_top_flow(player)
@tparam LuaPlayer player the player that you want to get the flow for
@treturn LuaGuiElement the top element flow
@usage-- Geting your top flow
local top_flow = Gui.get_top_flow(game.player)
]]
Gui.get_top_flow = mod_gui.get_button_flow
--[[-- Sets an element define to be drawn to the top flow when a player joins, includes optional authenticator
@tparam[opt] function authenticator called during toggle or update to decide weather the element should be visible
@treturn table the new element define to allow event handlers to be registered
@usage-- Adding an element to the top flow on join
example_button:add_to_top_flow(function(player)
-- example button will only be shown if the player is an admin
-- note button will not update its state when player.admin is changed Gui.update_top_flow must be called for this
return player.admin
end)
]]
function Gui._prototype_element:add_to_top_flow(authenticator)
ExpUtil.assert_not_runtime()
if not self.name then error("Elements for the top flow must have a static name") end
self.authenticator = authenticator or true
table.insert(Gui.top_elements, self)
return self
end
--- Returns true if the top flow has visible elements
function Gui.top_flow_has_visible_elements(player)
local top_flow = Gui.get_top_flow(player)
for _, child in pairs(top_flow.children) do
if child.name ~= hide_top_flow then
if child.visible then
return true
end
end
end
return false
end
Gui._top_flow_order_src = "<default>"
--- Get the order of elements in the top flow, first argument is player but is unused in the default method
function Gui.get_top_flow_order(_)
return Gui.top_elements
end
--- Inject a custom top flow order provider, this should accept a player and return a list of elements definitions to draw
function Gui.inject_top_flow_order(provider)
Gui.get_top_flow_order = provider
local debug_info = debug.getinfo(2, "Sn")
local file_name = debug_info.short_src:sub(10, -5)
local func_name = debug_info.name or ("<anonymous:" .. debug_info.linedefined .. ">")
Gui._top_flow_order_src = file_name .. ":" .. func_name
end
--[[-- Updates the visible state of all the elements on the players top flow, uses authenticator
@tparam LuaPlayer player the player that you want to update the top flow for
@usage-- Update your top flow
Gui.update_top_flow(game.player)
]]
function Gui.update_top_flow(player)
local top_flow = Gui.get_top_flow(player)
-- Get the order to draw the elements in
local flow_order = Gui.get_top_flow_order(player)
if #flow_order ~= #Gui.top_elements then
error(string.format("Top flow order provider (%s) did not return the correct element count, expect %d got %d",
Gui._top_flow_order_src, #Gui.top_elements, #flow_order
))
end
-- Set the visible state of all elements in the flow
for index, element_define in ipairs(flow_order) do
-- Ensure the element exists
local element = top_flow[element_define.name]
if not element then
element = element_define(top_flow)
else
top_flow.swap_children(index + 1, element.get_index_in_parent())
end
-- Set the visible state
local allowed = element_define.authenticator
if type(allowed) == "function" then allowed = allowed(player) end
element.visible = allowed or false
-- If its not visible and there is a left element, then hide it
if element_define.left_flow_element and not element.visible and Gui.left_flow_loaded(player, element_define.left_flow_element) then
Gui.toggle_left_element(player, element_define.left_flow_element, false)
end
end
-- Check if there are any visible elements in the top flow
if not Gui.top_flow_has_visible_elements(player) then
-- None are visible so hide the top_flow and its show button
Gui.toggle_top_flow(player, false)
local left_flow = Gui.get_left_flow(player)
local show_button = left_flow.gui_core_buttons[show_top_flow]
show_button.visible = false
end
end
--- Reorder the top flow elements to match that returned by the provider, uses a method equivalent to insert sort
function Gui.reorder_top_flow(player)
local top_flow = Gui.get_top_flow(player)
-- Get the order to draw the elements in
local flow_order = Gui.get_top_flow_order(player)
if #flow_order ~= #Gui.top_elements then
error(string.format("Top flow order provider (%s) did not return the correct element count, expect %d got %d",
Gui._top_flow_order_src, #Gui.top_elements, #flow_order
))
end
-- Reorder the elements, index 1 is the core ui buttons so +1 is required
for index, element_define in ipairs(flow_order) do
local element = top_flow[element_define.name]
top_flow.swap_children(index + 1, element.get_index_in_parent())
end
end
--[[-- Toggles the visible state of all the elements on a players top flow, effects all elements
@tparam LuaPlayer player the player that you want to toggle the top flow for
@tparam[opt] boolean state if given then the state will be set to this
@treturn boolean the new visible state of the top flow
@usage-- Toggle your flow
Gui.toggle_top_flow(game.player)
@usage-- Open your top flow
Gui.toggle_top_flow(game.player, true)
]]
function Gui.toggle_top_flow(player, state)
-- Get the top flow, we need the parent as we want to toggle the outer frame
local top_flow = Gui.get_top_flow(player).parent --- @cast top_flow -nil
if state == nil then state = not top_flow.visible end
-- Get the show button for the top flow
local left_flow = Gui.get_left_flow(player)
local show_button = left_flow.gui_core_buttons[show_top_flow]
-- Change the visibility of the top flow and show top flow button
show_button.visible = not state
top_flow.visible = state
return state
end
--[[-- Get the element define that is in the top flow, use in events without an element refrence
@tparam LuaPlayer player the player that you want to get the element for
@tparam table element_define the element that you want to get
@treturn LuaGuiElement the gui element linked to this define for this player
@usage-- Get your top element
local button = Gui.get_top_element(game.player, example_button)
]]
function Gui.get_top_element(player, element_define)
local top_flow = Gui.get_top_flow(player)
return assert(top_flow[element_define.name], "Top element failed to load")
end
--[[-- Toggles the state of a toolbar button for a given player, can be used to set the visual state
@tparam LuaPlayer player the player that you want to toggle the element for
@tparam table element_define the element that you want to toggle
@tparam[opt] boolean state with given will set the state, else state will be toggled
@treturn boolean the new visible state of the element
@usage-- Toggle your example button
Gui.toggle_toolbar_button(game.player, toolbar_button)
@usage-- Show your example button
Gui.toggle_toolbar_button(game.player, toolbar_button, true)
]]
function Gui.toggle_toolbar_button(player, element_define, state)
local toolbar_button = Gui.get_top_element(player, element_define)
if state == nil then state = toolbar_button.style.name ~= Gui.top_flow_button_toggled_style end
Gui.toolbar_button_style(toolbar_button, state, toolbar_button.style.minimal_width)
element_define:raise_event{
name = Gui.events.on_toolbar_button_toggled,
element = toolbar_button,
player = player,
state = state,
}
return state
end
--[[-- Creates a button on the top flow with consistent styling
@tparam string sprite the sprite that you want to use on the button
@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have
@tparam[opt] function authenticator used to decide if the button should be visible to a player
@usage-- Add a button to the toolbar
local toolbar_button =
Gui.left_toolbar_button('entity/inserter', 'Nothing to see here', function(player)
return player.admin
end)
]]
function Gui.toolbar_button(sprite, tooltip, authenticator)
return Gui.element{
type = "sprite-button",
sprite = sprite,
tooltip = tooltip,
style = Gui.top_flow_button_style,
name = Gui.unique_static_name,
}
:style{
minimal_width = toolbar_button_size,
height = toolbar_button_size,
padding = -2,
}
:add_to_top_flow(authenticator)
end
--[[-- Creates a toggle button on the top flow with consistent styling
@tparam string sprite the sprite that you want to use on the button
@tparam ?string|Concepts.LocalizedString tooltip the tooltip that you want the button to have
@tparam[opt] function authenticator used to decide if the button should be visible to a player
@usage-- Add a button to the toolbar
local toolbar_button =
Gui.toolbar_toggle_button('entity/inserter', 'Nothing to see here', function(player)
return player.admin
end)
:on_event(Gui.events.on_toolbar_button_toggled, function(player, element, event)
game.print(table.inspect(event))
end)
]]
function Gui.toolbar_toggle_button(sprite, tooltip, authenticator)
local button =
Gui.element{
type = "sprite-button",
sprite = sprite,
tooltip = tooltip,
style = Gui.top_flow_button_style,
name = Gui.unique_static_name,
}
:style{
minimal_width = toolbar_button_size,
height = toolbar_button_size,
padding = -2,
}
:add_to_top_flow(authenticator)
button:on_click(function(player, _, _)
Gui.toggle_toolbar_button(player, button)
end)
return button
end