Merge pull request #253 from Cooldude2606/feature/gui-event-tags

Feature/gui-event-tags
This commit is contained in:
Cooldude2606
2024-01-01 01:36:06 +00:00
committed by GitHub
20 changed files with 306 additions and 228 deletions

View File

@@ -18,7 +18,7 @@ Gui.element{
@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(event_trigger, parent, ...)
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 =
@@ -28,12 +28,12 @@ Gui.element(function(event_trigger, parent, ...)
}
-- Now we add the button to the flow that we created earlier
local element =
local element = definition:triggers_event(
flow.add{
name = event_trigger, -- event_trigger should be the name of any elements you want to trigger your event handlers
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

View File

@@ -16,7 +16,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/preset',
style = 'tool_button',
tooltip = {'gui_util.button_tooltip'}
tooltip = {'gui_util.button_tooltip'},
name = Gui.unique_static_name
}
:style{
padding = -2,
@@ -35,7 +36,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/preset',
style = 'tool_button',
tooltip = {'gui_util.button_tooltip'}
tooltip = {'gui_util.button_tooltip'},
name = Gui.unique_static_name
}
:style{
padding = -2,
@@ -54,7 +56,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/close_black',
style = 'tool_button',
tooltip = {'expcore-gui.left-button-tooltip'}
tooltip = {'expcore-gui.left-button-tooltip'},
name = Gui.unique_static_name
}
:style{
padding = -3,
@@ -83,5 +86,4 @@ Event.add(defines.events.on_player_created, function(event)
show_top.visible = false
hide_left.visible = false
Gui.draw_left_flow(player)
end)

View File

@@ -38,7 +38,8 @@ example_flow_with_button:add_to_left_flow(true)
]]
function Gui._prototype_element:add_to_left_flow(open_on_join)
Gui.left_elements[self.name] = open_on_join or false
if not self.name then error("Elements for the top flow must have a static name") end
Gui.left_elements[self] = open_on_join or false
return self
end
@@ -91,14 +92,14 @@ function Gui.draw_left_flow(player)
local hide_button = left_flow.gui_core_buttons[hide_left_flow]
local show_hide_button = false
for name, open_on_join in pairs(Gui.left_elements) do
for element_define, open_on_join in pairs(Gui.left_elements) do
-- Draw the element to the left flow
local draw_success, left_element = pcall(function()
return Gui.defines[name](left_flow)
end)
local draw_success, left_element = xpcall(function()
return element_define(left_flow)
end, debug.traceback)
if not draw_success then
error('There as been an error with an element draw function:\n\t'..left_element)
error('There as been an error with an element draw function: '..element_define.defined_at..'\n\t'..left_element)
end
-- Check if it should be open by default
@@ -116,7 +117,6 @@ function Gui.draw_left_flow(player)
show_hide_button = show_hide_button or visible
-- Get the assosiated element define
local element_define = Gui.defines[name]
local top_flow = Gui.get_top_flow(player)
-- Check if the the element has a button attached
@@ -144,8 +144,8 @@ 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 name, _ in pairs(Gui.left_elements) do
local left_element = left_flow[name]
for element_define, _ in pairs(Gui.left_elements) do
local left_element = left_flow[element_define.name]
if left_element.visible then
hide_button.visible = true
return true
@@ -169,11 +169,10 @@ function Gui.hide_left_flow(player)
-- Set the visible state of all elements in the flow
hide_button.visible = false
for name, _ in pairs(Gui.left_elements) do
left_flow[name].visible = false
for element_define, _ in pairs(Gui.left_elements) do
left_flow[element_define.name].visible = false
-- Check if the the element has a toobar button attached
local element_define = Gui.defines[name]
if element_define.toolbar_button then
-- Check if the topflow contains the button
local button = top_flow[element_define.toolbar_button]

View File

@@ -8,24 +8,29 @@ local Event = require '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 refrence
--- 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 debuging
--- 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 infomation about elements as they get defined such as the params used and event handlers registered to them
--- 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 = {
__call = function(self, parent, ...)
local element = self._draw(self.name, parent, ...)
local element = self._draw(self, parent, ...)
if self._style then self._style(element.style, element, ...) end
return element
if self.name and self.name ~= element.name then
error("Static name \""..self.name.."\" expected but got: "..tostring(element.name))
end
return element and self:triggers_events(element)
end
}
}
@@ -76,32 +81,38 @@ end)
]]
function Gui.element(element_define)
_C.error_if_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
local name = tostring(uid)
element.name = name
Gui.debug_info[name] = { draw = 'None', style = 'None', events = {} }
element.uid = uid
Gui.debug_info[uid] = { draw = 'None', style = 'None', events = {} }
-- Add the defination function
-- Add the definition function
if type(element_define) == 'table' then
Gui.debug_info[name].draw = element_define
element_define.name = name
Gui.debug_info[uid].draw = element_define
if element_define.name == Gui.unique_static_name then
element_define.name = "ExpGui_"..tostring(uid)
end
element.name = element_define.name
element._draw = function(_, parent)
return parent.add(element_define)
end
else
Gui.debug_info[name].draw = 'Function'
Gui.debug_info[uid].draw = 'Function'
element._draw = element_define
end
-- Add the define to the base module
local file_path = debug.getinfo(2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
Gui.file_paths[name] = file_path
Gui.defines[name] = element
local debug_info = debug.getinfo(2, "Sn")
local file_name = debug_info.source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
local func_name = debug_info.name or "<anonymous:"..debug_info.linedefined..">"
element.defined_at = file_name..":"..func_name
Gui.file_paths[uid] = element.defined_at
Gui.defines[uid] = element
-- Return the element so event handers can be accessed
return element
@@ -143,16 +154,16 @@ end)
]]
function Gui._prototype_element:style(style_define)
-- Add the defination function
-- Add the definition function
if type(style_define) == 'table' then
Gui.debug_info[self.name].style = style_define
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.name].style = 'Function'
Gui.debug_info[self.uid].style = 'Function'
self._style = style_define
end
@@ -160,6 +171,38 @@ function Gui._prototype_element:style(style_define)
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)
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
@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)
local tags = element.tags
if not tags then
element.tags = { ExpGui_event_triggers = { self.uid } }
return element
elseif not tags.ExpGui_event_triggers then
tags.ExpGui_event_triggers = { self.uid }
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
--[[-- 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
@@ -172,7 +215,7 @@ end)
]]
function Gui._prototype_element:on_custom_event(event_name, handler)
table.insert(Gui.debug_info[self.name].events, event_name)
table.insert(Gui.debug_info[self.uid].events, event_name)
Gui.events[event_name] = event_name
self[event_name] = handler
return self
@@ -210,7 +253,7 @@ function Gui._prototype_element:raise_custom_event(event)
end
event.player = player
local success, err = pcall(handler, player, element, event)
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
@@ -222,13 +265,18 @@ 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 element_define = Gui.defines[element.name]
if not element_define 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_custom_event(event)
end
end
end)
return function(self, handler)
table.insert(Gui.debug_info[self.name].events, debug.getinfo(1, "n").name)
table.insert(Gui.debug_info[self.uid].events, debug.getinfo(1, "n").name)
self[event_name] = handler
return self
end

View File

@@ -48,7 +48,8 @@ end)
]]
function Gui._prototype_element:add_to_top_flow(authenticator)
Gui.top_elements[self.name] = authenticator or true
if not self.name then error("Elements for the top flow must have a static name") end
Gui.top_elements[self] = authenticator or true
return self
end
@@ -65,11 +66,11 @@ function Gui.update_top_flow(player)
local is_visible = hide_button.visible
-- Set the visible state of all elements in the flow
for name, authenticator in pairs(Gui.top_elements) do
for element_define, authenticator in pairs(Gui.top_elements) do
-- Ensure the element exists
local element = top_flow[name]
local element = top_flow[element_define.name]
if not element then
element = Gui.defines[name](top_flow)
element = element_define(top_flow)
end
-- Set the visible state
@@ -138,7 +139,8 @@ function Gui.toolbar_button(sprite, tooltip, authenticator)
type = 'sprite-button',
sprite = sprite,
tooltip = tooltip,
style = Gui.top_flow_button_style
style = Gui.top_flow_button_style,
name = Gui.unique_static_name
}
:style{
minimal_width = 36,

View File

@@ -103,15 +103,17 @@ end
--- Label used to show that the player is following, also used to allow esc to stop following
-- @element follow_label
follow_label =
Gui.element(function(event_trigger, parent, target)
Gui.destroy_if_valid(parent[event_trigger])
Gui.element(function(definition, parent, target)
Gui.destroy_if_valid(parent[definition.name])
local label = parent.add{
name = event_trigger,
local label = definition:triggers_events(
parent.add{
type = 'label',
style = 'heading_1_label',
caption = 'Following '..target.name..'.\nClick here or press esc to stop following.'
caption = 'Following '..target.name..'.\nClick here or press esc to stop following.',
name = definition.name
}
)
local player = Gui.get_player_from_element(parent)
local res = player.display_resolution
@@ -122,6 +124,7 @@ Gui.element(function(event_trigger, parent, target)
return label
end)
:static_name(Gui.unique_static_name)
:on_click(Public.stop_follow)
:on_close(function(player)
-- Don't call set_controller during on_close as it invalidates the controller

View File

@@ -32,7 +32,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/expand_dark',
hovered_sprite = 'utility/expand',
tooltip = {'autofill.toggle-section-tooltip'}
tooltip = {'autofill.toggle-section-tooltip'},
name = Gui.unique_static_name
}
:style(Gui.sprite_style(20))
:on_click(function(_, element, _)
@@ -50,25 +51,16 @@ Gui.element{
end
end)
--- Used to assign an event to the header label to trigger a toggle
-- @element header_toggle
local header_toggle = Gui.element()
:on_click(function(_, element, event)
event.element = element.parent.alignment[toggle_section.name]
toggle_section:raise_custom_event(event)
end)
--- Toggle enitity button, used for toggling autofill for the specific entity
-- All entity autofill settings will be ignored if its disabled
-- @element entity_toggle
local entity_toggle = Gui.element(function(event_trigger, parent, entity_name)
return parent.add{
name = event_trigger,
local entity_toggle = Gui.element(function(definition, parent, entity_name)
return definition:triggers_events(parent.add{
type = 'sprite-button',
sprite = 'utility/confirm_slot',
tooltip = {'autofill.toggle-entity-tooltip', rich_img('item', entity_name)},
style = 'shortcut_bar_button_green'
}
})
end)
:style(Gui.sprite_style(22))
:on_click(function(player, element, _)
@@ -95,16 +87,18 @@ end)
--- Draw a section header and main scroll
-- @element autofill_section_container
local section =
Gui.element(function(_, parent, section_name, table_size)
Gui.element(function(definition, parent, section_name, table_size)
-- Draw the header for the section
local header = Gui.header(
parent,
{'autofill.toggle-section-caption', rich_img('item', section_name), {'entity-name.'..section_name}},
{'autofill.toggle-section-tooltip'},
true,
section_name..'-header',
header_toggle.name
section_name..'-header'
)
definition:triggers_events(header.parent.header_label)
-- Right aligned button to toggle the section
header.caption = section_name
entity_toggle(header, section_name)
@@ -120,13 +114,16 @@ Gui.element(function(_, parent, section_name, table_size)
return section_table
end)
:on_click(function(_, element, event)
event.element = element.parent.alignment[toggle_section.name]
toggle_section:raise_custom_event(event)
end)
--- Toggle item button, used for toggling autofill for the specific item
-- @element toggle_item_button
local toggle_item_button =
Gui.element(function(event_trigger, parent, item)
Gui.element(function(_, parent, item)
return parent.add{
name = event_trigger,
type = 'sprite-button',
sprite = 'item/'..item.name,
tooltip = {'autofill.toggle-tooltip', rich_img('item', item.name), item.category},
@@ -161,9 +158,8 @@ end)
--- Amount text field for a autofill item
-- @element amount_textfield
local amount_textfield =
Gui.element(function(event_trigger, parent, item)
Gui.element(function(_, parent, item)
return parent.add{
name = event_trigger,
type = 'textfield',
text = item.amount,
tooltip = {'autofill.amount-tooltip', item.category },
@@ -233,9 +229,9 @@ end)
--- Main gui container for the left flow
-- @element autofill_container
autofill_container =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
-- Draw the internal container
local container = Gui.container(parent, event_trigger)
local container = Gui.container(parent, definition.name)
-- Draw the scroll container
local scroll_table = Gui.scroll_table(container, 400, 1, 'autofill-scroll-table')
-- Set the scroll panel to always show the scrollbar (not doing this will result in a changing gui size)
@@ -293,6 +289,7 @@ Gui.element(function(event_trigger, parent)
-- Return the external container
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
--- Button on the top flow used to toggle autofill container

View File

@@ -171,7 +171,6 @@ end
local button_apply =
Gui.element{
name = 'module_b',
type = 'button',
caption = 'Apply',
style = 'button'
@@ -184,8 +183,8 @@ Gui.element{
end)
module_container =
Gui.element(function(event_trigger, parent)
local container = Gui.container(parent, event_trigger, (config.module_slot_max + 2) * 36)
Gui.element(function(definition, parent)
local container = Gui.container(parent, definition.name, (config.module_slot_max + 2) * 36)
Gui.header(container, 'Module Inserter', '', true)
local scroll_table = Gui.scroll_table(container, (config.module_slot_max + 2) * 36, config.module_slot_max + 1)
@@ -214,6 +213,7 @@ Gui.element(function(event_trigger, parent)
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
Gui.left_toolbar_button('item/productivity-module-3', {'module.main-tooltip'}, module_container, function(player)

View File

@@ -29,7 +29,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/expand_dots_white',
tooltip = {'player-list.open-action-bar'},
style = 'frame_button'
style = 'frame_button',
name = Gui.unique_static_name
}
:style{
padding = -2,
@@ -85,21 +86,21 @@ end)
--- Set of elements that are used to make up a row of the player table
-- @element add_player_base
local add_player_base =
Gui.element(function(event_trigger, parent, player_data)
Gui.element(function(definition, parent, player_data)
-- Add the button to open the action bar
local toggle_action_bar_flow = parent.add{ type = 'flow', name = player_data.name }
open_action_bar(toggle_action_bar_flow)
-- Add the player name
local player_name_flow = parent.add{ type = 'flow', name = 'player-name-'..player_data.index }
local player_name = player_name_flow.add{
local player_name = parent.add{
type = 'label',
name = event_trigger,
name = 'player-name-'..player_data.index,
caption = player_data.name,
tooltip = {'player-list.open-map', player_data.name, player_data.tag, player_data.role_name}
}
player_name.style.padding = {0, 2,0, 0}
player_name.style.font_color = player_data.chat_color
definition:triggers_events(player_name)
-- Add the time played label
local alignment = Gui.alignment(parent, 'player-time-'..player_data.index)
@@ -202,9 +203,9 @@ end
--- Main player list container for the left flow
-- @element player_list_container
local player_list_container =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
-- Draw the internal container
local container = Gui.container(parent, event_trigger, 200)
local container = Gui.container(parent, definition.name, 200)
-- Draw the scroll table for the players
local scroll_table = Gui.scroll_table(container, 184, 3)
@@ -255,6 +256,7 @@ Gui.element(function(event_trigger, parent)
-- Return the exteral container
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow(true)
--- Button on the top flow used to toggle the player list container

View File

@@ -16,13 +16,11 @@ local label_width = {
['total'] = 480
}
local function format_clock(value)
local function format_time_short(value)
return format_time(value*3600, {
hours=true,
minutes=true,
seconds=false,
time=false,
string=true
seconds=false
})
end
@@ -33,49 +31,49 @@ end
local playerStats = PlayerData.Statistics
local computed_stats = {
DamageDeathRatio = {
default = '0.00',
default = format_number_n(0),
calculate = function(player_name)
return format_number_n(playerStats['DamageDealt']:get(player_name, 0) / playerStats['Deaths']:get(player_name, 1))
end
},
KillDeathRatio = {
default = '0.00',
default = format_number_n(0),
calculate = function(player_name)
return format_number_n(playerStats['Kills']:get(player_name, 0) / playerStats['Deaths']:get(player_name, 1))
end
},
SessionTime = {
default = format_clock(0),
default = format_time_short(0),
calculate = function(player_name)
return format_clock((playerStats['Playtime']:get(player_name, 0) - playerStats['AfkTime']:get(player_name, 0)) / playerStats['JoinCount']:get(player_name, 1))
return format_time_short((playerStats['Playtime']:get(player_name, 0) - playerStats['AfkTime']:get(player_name, 0)) / playerStats['JoinCount']:get(player_name, 1))
end
},
BuildRatio = {
default = '0.00',
default = format_number_n(0),
calculate = function(player_name)
return format_number_n(playerStats['MachinesBuilt']:get(player_name, 0) / playerStats['MachinesRemoved']:get(player_name, 1))
end
},
RocketPerHour = {
default = '0.00',
default = format_number_n(0),
calculate = function(player_name)
return format_number_n(playerStats['RocketsLaunched']:get(player_name, 0) * 60 / playerStats['Playtime']:get(player_name, 1))
end
},
TreeKillPerMinute = {
default = '0.00',
default = format_number_n(0),
calculate = function(player_name)
return format_number_n(playerStats['TreesDestroyed']:get(player_name, 0) / playerStats['Playtime']:get(player_name, 1))
end
},
NetPlayTime = {
default = format_clock(0),
default = format_time_short(0),
calculate = function(player_name)
return format_clock((playerStats['Playtime']:get(player_name, 0) - playerStats['AfkTime']:get(player_name, 0)))
return format_time_short((playerStats['Playtime']:get(player_name, 0) - playerStats['AfkTime']:get(player_name, 0)))
end
},
AFKTimeRatio = {
default = '0.00',
default = format_number_n(0),
calculate = function(player_name)
return format_number_n(playerStats['AfkTime']:get(player_name, 0) * 100 / playerStats['Playtime']:get(player_name, 1))
end
@@ -137,9 +135,9 @@ local function pd_update(table, player_name)
end
local pd_username_player =
Gui.element(function(name, parent, player_list)
Gui.element(function(definition, parent, player_list)
return parent.add{
name = name,
name = definition.name,
type = 'drop-down',
items = player_list,
selected_index = #player_list > 0 and 1
@@ -152,10 +150,12 @@ end)
local table = element.parent.parent.parent.parent['pd_st_2'].disp.table
pd_update(table, player_name)
end)
:static_name(Gui.unique_static_name)
local pd_username_update =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'update'
}:style{
width = 128
@@ -181,8 +181,8 @@ Gui.element(function(_, parent, name, player_list)
end)
pd_container =
Gui.element(function(event_trigger, parent)
local container = Gui.container(parent, event_trigger, label_width['total'])
Gui.element(function(definition, parent)
local container = Gui.container(parent, definition.name, label_width['total'])
local player_list = {}
for _, player in pairs(game.connected_players) do
@@ -194,6 +194,7 @@ Gui.element(function(event_trigger, parent)
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
Gui.left_toolbar_button('item/power-armor-mk2', 'Player Data GUI', pd_container, function(player)

View File

@@ -25,13 +25,11 @@ local scroll_height = 275 -- controls the height of the scrolls
--- Sub content area used within the content areas
-- @element sub_content
local sub_content =
Gui.element(function(_, parent)
return parent.add{
Gui.element{
type = 'frame',
direction = 'vertical',
style = 'inside_deep_frame'
}
end)
}
:style{
horizontally_stretchable = true,
horizontal_align = 'center',
@@ -77,17 +75,16 @@ Gui.element{
--- Used to connect to servers in server list
-- @element join_server
local join_server =
Gui.element(function(event_trigger, parent, server_id, wrong_version)
Gui.element(function(definition, parent, server_id, wrong_version)
local status = External.get_server_status(server_id) or 'Offline'
if wrong_version then status = 'Version' end
local flow = parent.add{ name = server_id, type = 'flow' }
local button = flow.add{
name = event_trigger,
local button = definition:triggers_events(flow.add{
type = 'sprite-button',
sprite = 'utility/circuit_network_panel_white', --- network panel white, warning white, download white
hovered_sprite = 'utility/circuit_network_panel_black', --- network panel black, warning black, download black
tooltip = {'readme.servers-connect-'..status, wrong_version}
}
})
if status == 'Offline' or status == 'Current' then
button.enabled = false
@@ -404,9 +401,9 @@ end))
-- @element readme
local readme_toggle
local readme =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
local container = parent.add{
name = event_trigger,
name = definition.name,
type = 'frame',
style = 'invisible_frame'
}
@@ -439,6 +436,7 @@ Gui.element(function(event_trigger, parent)
return container
end)
:static_name(Gui.unique_static_name)
:on_open(function(player)
local toggle_button = Gui.get_top_element(player, readme_toggle)
Gui.toolbar_button_style(toggle_button, true)

View File

@@ -55,8 +55,8 @@ for i=1, #config.milestone do
end
local clock_container =
Gui.element(function(event_trigger, parent)
local container = Gui.container(parent, event_trigger, 200)
Gui.element(function(definition, parent)
local container = Gui.container(parent, definition.name, 200)
local scroll_table = Gui.scroll_table(container, 400, 4)
scroll_table.add{
@@ -143,6 +143,7 @@ Gui.element(function(event_trigger, parent)
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
Gui.left_toolbar_button('item/space-science-pack', {'expcom-res.main-tooltip'}, clock_container, function(player)

View File

@@ -43,7 +43,8 @@ local toggle_launch =
Gui.element{
type = 'sprite-button',
sprite = 'utility/play',
tooltip = {'rocket-info.toggle-rocket-tooltip'}
tooltip = {'rocket-info.toggle-rocket-tooltip'},
name = Gui.unique_static_name
}
:style(Gui.sprite_style(16))
:on_click(function(_, element, _)
@@ -66,7 +67,8 @@ local launch_rocket =
Gui.element{
type = 'sprite-button',
sprite = 'utility/center',
tooltip = {'rocket-info.launch-tooltip'}
tooltip = {'rocket-info.launch-tooltip'},
name = Gui.unique_static_name
}
:style(Gui.sprite_style(16, -1))
:on_click(function(player, element, _)
@@ -82,10 +84,9 @@ end)
--- XY cords that allow zoom to map when pressed
-- @element silo_cords
local silo_cords =
Gui.element(function(event_trigger, parent, silo_data)
Gui.element(function(definition, parent, silo_data)
local silo_name = silo_data.silo_name
local pos = silo_data.position
local name = config.progress.allow_zoom_to_map and event_trigger or nil
local tooltip = config.progress.allow_zoom_to_map and {'rocket-info.progress-label-tooltip'} or nil
-- Add the x cord flow
@@ -97,9 +98,8 @@ Gui.element(function(event_trigger, parent, silo_data)
flow_x.style.padding = {0, 2,0, 1}
-- Add the x cord label
flow_x.add{
local label_x = flow_x.add{
type = 'label',
name = name,
caption = {'rocket-info.progress-x-pos', pos.x},
tooltip = tooltip
}
@@ -113,13 +113,16 @@ Gui.element(function(event_trigger, parent, silo_data)
flow_y.style.padding = {0, 2,0, 1}
-- Add the y cord label
flow_y.add{
local label_y = flow_y.add{
type = 'label',
name = name,
caption = {'rocket-info.progress-y-pos', pos.y},
tooltip = tooltip
}
if config.progress.allow_zoom_to_map then
definition:triggers_events(label_x)
definition:triggers_events(label_y)
end
end)
:on_click(function(player, element, _)
local rocket_silo_name = element.parent.caption
@@ -422,7 +425,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/expand_dark',
hovered_sprite = 'utility/expand',
tooltip = {'rocket-info.toggle-section-tooltip'}
tooltip = {'rocket-info.toggle-section-tooltip'},
name = Gui.unique_static_name
}
:style(Gui.sprite_style(20))
:on_click(function(_, element, _)
@@ -440,27 +444,19 @@ Gui.element{
end
end)
-- Used to assign an event to the header label to trigger a toggle
-- @element header_toggle
local header_toggle = Gui.element()
:on_click(function(_, element, event)
event.element = element.parent.alignment[toggle_section.name]
toggle_section:raise_custom_event(event)
end)
-- Draw a section header and main scroll
-- @element rocket_list_container
local section =
Gui.element(function(_, parent, section_name, table_size)
Gui.element(function(definition, parent, section_name, table_size)
-- Draw the header for the section
local header = Gui.header(
parent,
{'rocket-info.section-caption-'..section_name},
{'rocket-info.section-tooltip-'..section_name},
true,
section_name..'-header',
header_toggle.name
section_name..'-header'
)
definition:triggers_events(header.parent.header_label)
-- Right aligned button to toggle the section
header.caption = section_name
@@ -473,13 +469,17 @@ Gui.element(function(_, parent, section_name, table_size)
-- Return the flow table
return scroll_table
end)
:on_click(function(_, element, event)
event.element = element.parent.alignment[toggle_section.name]
toggle_section:raise_custom_event(event)
end)
--- Main gui container for the left flow
-- @element rocket_list_container
local rocket_list_container =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
-- Draw the internal container
local container = Gui.container(parent, event_trigger, 200)
local container = Gui.container(parent, definition.name, 200)
-- Set the container style
local style = container.style
@@ -516,6 +516,7 @@ Gui.element(function(event_trigger, parent)
-- Return the exteral container
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow(function(player)
return player.force.rockets_launched > 0 and Roles.player_allowed(player, 'gui/rocket-info')
end)

View File

@@ -261,11 +261,11 @@ end
--- Main task list container for the left flow
-- @element task_list_container
local science_info_container =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
local player = Gui.get_player_from_element(parent)
-- Draw the internal container
local container = Gui.container(parent, event_trigger, 200)
local container = Gui.container(parent, definition.name, 200)
-- Draw the header
Gui.header(container, {'science-info.main-caption'}, {'science-info.main-tooltip'})
@@ -315,6 +315,7 @@ Gui.element(function(event_trigger, parent)
-- Return the exteral container
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
--- Button on the top flow used to toggle the task list container

View File

@@ -23,7 +23,8 @@ UsesServerUps:set_metadata{
local server_ups =
Gui.element{
type = 'label',
caption = 'SUPS = 60.0'
caption = 'SUPS = 60.0',
name = Gui.unique_static_name
}
:style{
font = 'default-game'

View File

@@ -5,12 +5,10 @@ local Gui = require 'expcore.gui' --- @dep expcore.gui
local Roles = require 'expcore.roles' --- @dep expcore.roles
local Event = require 'utils.event' --- @dep utils.event
local cctv_container
local cctv_player =
Gui.element(function(name, parent, player_list)
Gui.element(function(definition, parent, player_list)
return parent.add{
name = name,
name = definition.name,
type = 'drop-down',
items = player_list,
selected_index = #player_list > 0 and 1
@@ -19,11 +17,11 @@ end)
:style{
horizontally_stretchable = true
}
:static_name(Gui.unique_static_name)
local cctv_type =
local cctv_status =
Gui.element{
type = 'drop-down',
name = 'cctv_status',
items = {'Enable', 'Disable'},
selected_index = 2
}:style{
@@ -36,10 +34,10 @@ Gui.element{
end
end)
local cctv_status =
local cctv_type =
Gui.element{
type = 'drop-down',
name = 'cctv_status',
name = Gui.unique_static_name,
items = {'Player', 'Static'},
selected_index = 1
}:style{
@@ -49,6 +47,7 @@ Gui.element{
local cctv_location =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'set'
}:style{
width = 48
@@ -59,6 +58,7 @@ end)
local zoom_in =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = '+'
}:style{
width = 32
@@ -72,6 +72,7 @@ end)
local zoom_out =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = '-'
}:style{
width = 32
@@ -88,8 +89,8 @@ Gui.element(function(_, parent, name, player_list)
local buttons = Gui.scroll_table(camera_set, 480, 6, 'buttons')
cctv_player(buttons, player_list)
cctv_type(buttons)
cctv_status(buttons)
cctv_type(buttons)
cctv_location(buttons)
zoom_out(buttons)
zoom_in(buttons)
@@ -108,9 +109,9 @@ Gui.element(function(_, parent, name, player_list)
return camera_set
end)
cctv_container =
Gui.element(function(event_trigger, parent)
local container = Gui.container(parent, event_trigger, 480)
local cctv_container =
Gui.element(function(definition, parent)
local container = Gui.container(parent, definition.name, 480)
local scroll = container.add{name='scroll', type='scroll-pane', direction='vertical'}
scroll.style.maximal_height = 704
local player_list = {}
@@ -124,6 +125,7 @@ Gui.element(function(event_trigger, parent)
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
Gui.left_toolbar_button('entity/radar', 'Surveillance GUI', cctv_container, function(player)
@@ -154,7 +156,7 @@ Event.add(defines.events.on_tick, function(_)
for i=1, 2 do
local scroll_table_name = 'cctv_st_' .. i
local current_camera_set = frame.container.scroll[scroll_table_name]
local switch_index = current_camera_set.buttons.table[cctv_status.name].selected_index
local switch_index = current_camera_set.buttons.table[cctv_type.name].selected_index
if switch_index == 1 then
local selected_index = current_camera_set.buttons.table[cctv_player.name].selected_index

View File

@@ -85,7 +85,8 @@ local add_new_task =
type = "sprite-button",
sprite = "utility/add",
tooltip = {"task-list.add-tooltip"},
style = "tool_button"
style = "tool_button",
name = Gui.unique_static_name
}:style(Styles.sprite22):on_click(
function(player, _, _)
-- Disable editing
@@ -164,20 +165,16 @@ local subfooter_label =
--- Action flow that contains action buttons
-- @element subfooter_actions
local subfooter_actions =
Gui.element(
function(_, parent)
return parent.add {
Gui.element {
type = "flow",
name = "actions"
}
end
)
}
--- Button element with a flow around it to fix duplicate name inside of the scroll flow
-- @element task_list_item
local task_list_item =
Gui.element(
function(event_trigger, parent, task)
function(definition, parent, task)
local flow =
parent.add {
type = "flow",
@@ -187,11 +184,12 @@ local task_list_item =
flow.style.horizontally_stretchable = true
local button =
flow.add {
name = event_trigger,
name = definition.name,
type = "button",
style = "list_box_item",
caption = task.title
}
definition:triggers_events(button)
button.style.horizontally_stretchable = true
button.style.horizontally_squashable = true
return flow
@@ -201,7 +199,7 @@ local task_list_item =
local task_id = element.parent.caption
PlayerSelected:set(player, task_id)
end
)
):static_name(Gui.unique_static_name)
--- Scrollable list of all tasks
-- @element task_list
@@ -239,6 +237,7 @@ local task_list =
local task_view_edit_button =
Gui.element {
type = "button",
name = Gui.unique_static_name,
caption = {"", "[img=utility/rename_icon_normal] ", {"task-list.edit"}},
tooltip = {"task-list.edit-tooltip"},
style = "shortcut_bar_button"
@@ -271,6 +270,7 @@ Gui.element{
local task_view_delete_button =
Gui.element {
type = "button",
name = Gui.unique_static_name,
caption = {"", "[img=utility/trash] ", {"task-list.delete"}},
tooltip = {"task-list.delete-tooltip"},
style = "shortcut_bar_button_red"
@@ -342,6 +342,7 @@ local task_create_confirm_button
-- @element task_message_textfield
local task_message_textfield =
Gui.element {
name = Gui.unique_static_name,
type = "text-box",
text = ""
}:style(
@@ -370,6 +371,7 @@ local task_message_textfield =
task_edit_confirm_button =
Gui.element {
type = "button",
name = Gui.unique_static_name,
caption = {"", "[img=utility/check_mark] ", {"task-list.confirm"}},
tooltip = {"task-list.confirm-tooltip"},
style = "shortcut_bar_button_green"
@@ -424,6 +426,7 @@ local task_edit_footer =
task_create_confirm_button =
Gui.element {
type = "button",
name = Gui.unique_static_name,
caption = {"", "[img=utility/check_mark] ", {"task-list.confirm"}},
tooltip = {"task-list.confirm-tooltip"},
style = "shortcut_bar_button_green",
@@ -496,9 +499,9 @@ end
-- @element task_list_container
local task_list_container =
Gui.element(
function(event_trigger, parent)
function(definition, parent)
-- Draw the internal container
local container = Gui.container(parent, event_trigger, 268)
local container = Gui.container(parent, definition.name, 268)
container.style.maximal_width = 268
container.style.minimal_width = 268
@@ -526,7 +529,7 @@ local task_list_container =
-- Return the external container
return container.parent
end
):add_to_left_flow(
):static_name(Gui.unique_static_name):add_to_left_flow(
function(player)
local task_ids = Tasks.get_force_task_ids(player.force.name)
return #task_ids > 0

View File

@@ -229,6 +229,7 @@ end
local vlayer_gui_control_storage_input =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'Add Input Storage'
}:style{
width = 160
@@ -248,6 +249,7 @@ end)
local vlayer_gui_control_storage_output =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'Add Output Storage'
}:style{
width = 160
@@ -267,6 +269,7 @@ end)
local vlayer_gui_control_circuit =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'Add Circuit'
}:style{
width = 160
@@ -286,6 +289,7 @@ end)
local vlayer_gui_control_power =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'Add Power'
}:style{
width = 160
@@ -308,6 +312,7 @@ end)
local vlayer_gui_control_remove =
Gui.element{
type = 'button',
name = Gui.unique_static_name,
caption = 'Remove Special'
}:style{
width = 160
@@ -345,9 +350,9 @@ end)
--- The main container for the vlayer gui
-- @element vlayer_container
local vlayer_container =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
local player = Gui.get_player_from_element(parent)
local container = Gui.container(parent, event_trigger, 320)
local container = Gui.container(parent, definition.name, 320)
vlayer_display_set(container, 'vlayer_st_1')
vlayer_control_set(container, 'vlayer_st_2')
@@ -362,6 +367,7 @@ Gui.element(function(event_trigger, parent)
table[vlayer_gui_control_remove.name].visible = visible
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
--- Button on the top flow used to toggle the task list container

View File

@@ -81,7 +81,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/add',
tooltip = {'warp-list.add-tooltip'},
style = 'shortcut_bar_button'
style = 'shortcut_bar_button',
name = Gui.unique_static_name
}
:style(Styles.sprite22)
:on_click(function(player, _)
@@ -148,7 +149,7 @@ end)
--- Warp icon button, this will trigger a warp when the player is able to
-- @element warp_icon_button
local warp_icon_button =
Gui.element(function(event_trigger, parent, warp)
Gui.element(function(definition, parent, warp)
local warp_position = warp.position
-- The SpritePath type is not the same as the SignalID type
@@ -158,15 +159,16 @@ Gui.element(function(event_trigger, parent, warp)
end
-- Draw the element
return parent.add{
name = event_trigger,
return definition:triggers_events(parent.add{
type = 'sprite-button',
sprite = sprite,
name = definition.name,
tooltip = {'warp-list.goto-tooltip', warp_position.x, warp_position.y},
style = 'slot_button'
}
})
end)
:style(Styles.sprite32)
:static_name(Gui.unique_static_name)
:on_click(function(player, element, _)
if element.type == 'choose-elem-button' then return end
local warp_id = element.parent.caption
@@ -183,30 +185,31 @@ end)
--- The button that is visible when the warp is in edit state
-- @element warp_icon_editing
local warp_icon_editing =
Gui.element(function(event_trigger, parent, warp)
return parent.add{
name = event_trigger,
Gui.element(function(definition, parent, warp)
return definition:triggers_events(parent.add{
name = definition.name,
type = 'choose-elem-button',
elem_type = 'signal',
signal = {type = warp.icon.type, name = warp.icon.name},
tooltip = {'warp-list.goto-edit'}
}
})
end)
:static_name(Gui.unique_static_name)
:style(Styles.sprite32)
--- Warp label, visible if the player is not in edit state
-- @element warp_label
local warp_label =
Gui.element(function(event_trigger, parent, warp)
Gui.element(function(definition, parent, warp)
local last_edit_name = warp.last_edit_name
local last_edit_time = warp.last_edit_time
-- Draw the element
return parent.add{
name = event_trigger,
return definition:triggers_events(parent.add{
type = 'label',
caption = warp.name,
tooltip = {'warp-list.last-edit', last_edit_name, format_time(last_edit_time)}
}
tooltip = {'warp-list.last-edit', last_edit_name, format_time(last_edit_time)},
name = definition.name
})
end)
:style{
single_line = true,
@@ -220,19 +223,17 @@ end)
local position = warp.position
player.zoom_to_world(position, 1.5)
end)
:static_name(Gui.unique_static_name)
--- Warp status, visible if the player is not in edit state
--- This will show if the warp is connected or not
-- @element warp_status
local warp_status =
Gui.element(function(event_trigger, parent)
-- Draw the element
return parent.add{
name = event_trigger,
Gui.element{
type = 'label',
caption = '[img=utility/electricity_icon_unplugged]', -- Temporary icon
}
end)
name = Gui.unique_static_name
}
:style{
-- When editing mode because textbox is larger the icon would move up.
top_padding = 1,
@@ -242,14 +243,14 @@ end)
--- Warp textfield, visible if the player is in edit state
-- @element warp_textfield
local warp_textfield =
Gui.element(function(event_trigger, parent, warp)
Gui.element(function(definition, parent, warp)
-- Draw the element
return parent.add{
name = event_trigger,
return definition:triggers_events(parent.add{
type = 'textfield',
text = warp.name,
clear_and_focus_on_right_click = true
}
clear_and_focus_on_right_click = true,
name = definition.name
})
end)
:style{
-- Required fields to make it squashable and strechable.
@@ -270,6 +271,7 @@ end)
Warps.set_editing(warp_id, player.name)
Warps.update_warp(warp_id, warp_name, warp_icon, player.name)
end)
:static_name(Gui.unique_static_name)
--- Confirms the edit to name or icon of the warp
@@ -279,7 +281,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/confirm_slot',
tooltip = {'warp-list.confirm-tooltip'},
style = 'shortcut_bar_button_green'
style = 'shortcut_bar_button_green',
name = Gui.unique_static_name
}
:style(Styles.sprite22)
:on_click(function(player, element)
@@ -297,7 +300,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/close_black',
tooltip = {'warp-list.cancel-tooltip'},
style = 'shortcut_bar_button_red'
style = 'shortcut_bar_button_red',
name = Gui.unique_static_name
}
:style(Styles.sprite22)
:on_click(function(player, element)
@@ -318,7 +322,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/trash',
tooltip = {'warp-list.remove-tooltip'},
style = 'shortcut_bar_button_red'
style = 'shortcut_bar_button_red',
name = Gui.unique_static_name
}
:style(Styles.sprite22)
:on_click(function(_, element)
@@ -333,7 +338,8 @@ Gui.element{
type = 'sprite-button',
sprite = 'utility/rename_icon_normal',
tooltip = {'warp-list.edit-tooltip-none'},
style = 'shortcut_bar_button'
style = 'shortcut_bar_button',
name = Gui.unique_static_name
}
:style(Styles.sprite22)
:on_click(function(player, element)
@@ -402,6 +408,7 @@ end
local warp_timer =
Gui.element{
type = 'progressbar',
name = Gui.unique_static_name,
tooltip = {'warp-list.timer-tooltip-zero', config.cooldown_duration},
minimum_value = 0,
maximum_value = config.cooldown_duration*config.update_smoothing
@@ -626,13 +633,13 @@ end
--- Main warp list container for the left flow
-- @element warp_list_container
warp_list_container =
Gui.element(function(event_trigger, parent)
Gui.element(function(definition, parent)
local player = Gui.get_player_from_element(parent)
-- Check if user has permission to add warps
local allow_add_warp = check_player_permissions(player, 'allow_add_warp')
-- Draw the internal container
local container = Gui.container(parent, event_trigger, allow_add_warp and 268 or 220)
local container = Gui.container(parent, definition.name, allow_add_warp and 268 or 220)
-- Draw the header
local header = Gui.header(
@@ -685,6 +692,7 @@ Gui.element(function(event_trigger, parent)
-- Return the external container
return container.parent
end)
:static_name(Gui.unique_static_name)
:add_to_left_flow()
--- Button on the top flow used to toggle the warp list container

View File

@@ -1,8 +1,10 @@
local Global = require 'utils.global' --- @dep utils.global
local ExpGui = require 'expcore.gui' --- @dep expcore.gui
local Event = require 'utils.event' --- @dep expcore.gui
local mod_gui = require 'mod-gui' --- @dep mod-gui
local Gui = {}
local data = {}
local uid = 0
Global.register(
data,
@@ -12,8 +14,8 @@ Global.register(
)
function Gui.uid_name()
local new_element = ExpGui.element()
return new_element.name
uid = uid + 1
return "Redmew_"..uid
end
-- Associates data with the LuaGuiElement. If data is nil then removes the data
@@ -70,10 +72,11 @@ end
local function handler_factory(event_name)
return function(element_name, handler)
local element = ExpGui.defines[element_name]
if not element then return end
element[event_name](element, function(_, _,event)
Event.add(defines.events[event_name], function(event)
if event.element and event.element.valid and event.element.name == element_name then
event.player = game.get_player(event.player_index)
handler(event)
end
end)
end
end
@@ -82,48 +85,48 @@ end
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_checked_state_changed = handler_factory('on_checked_changed')
Gui.on_checked_state_changed = handler_factory('on_gui_checked_state_changed')
-- Register a handler for the on_gui_click event for LuaGuiElements with element_name.
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_click = handler_factory('on_click')
Gui.on_click = handler_factory('on_gui_click')
-- Register a handler for the on_gui_closed event for a custom LuaGuiElements with element_name.
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_custom_close = handler_factory('on_closed')
Gui.on_custom_close = handler_factory('on_gui_closed')
-- Register a handler for the on_gui_elem_changed event for LuaGuiElements with element_name.
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_elem_changed = handler_factory('on_elem_changed')
Gui.on_elem_changed = handler_factory('on_gui_elem_changed')
-- Register a handler for the on_gui_selection_state_changed event for LuaGuiElements with element_name.
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_selection_state_changed = handler_factory('on_selection_changed')
Gui.on_selection_state_changed = handler_factory('on_gui_selection_state_changed')
-- Register a handler for the on_gui_text_changed event for LuaGuiElements with element_name.
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_text_changed = handler_factory('on_text_changed')
Gui.on_text_changed = handler_factory('on_gui_text_changed')
-- Register a handler for the on_gui_value_changed event for LuaGuiElements with element_name.
-- Can only have one handler per element name.
-- Guarantees that the element and the player are valid when calling the handler.
-- Adds a player field to the event table.
Gui.on_value_changed = handler_factory('on_value_changed')
Gui.on_value_changed = handler_factory('on_gui_value_changed')
--- Returns the flow where top elements can be added and will be effected by google visibility
-- For the toggle to work it must be registed with Gui.allow_player_to_toggle_top_element_visibility(element_name)
-- @tparam LuaPlayer player pointer to the player who has the gui
-- @treturn LuaGuiElement the top element flow
Gui.get_top_element_flow = ExpGui.get_top_flow
Gui.get_top_element_flow = mod_gui.get_button_flow
return Gui