mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Convert toolbar minus datastore
This commit is contained in:
@@ -103,7 +103,7 @@ end
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function ExpGui.get_top_element(define, player)
|
function ExpGui.get_top_element(define, player)
|
||||||
return player_elements[player.index].top[define.name]
|
return assert(player_elements[player.index].top[define.name], "Element is not on the top flow")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Register a element define to be drawn to the left flow on join
|
--- Register a element define to be drawn to the left flow on join
|
||||||
@@ -111,7 +111,7 @@ end
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function ExpGui.get_left_element(define, player)
|
function ExpGui.get_left_element(define, player)
|
||||||
return player_elements[player.index].left[define.name]
|
return assert(player_elements[player.index].left[define.name], "Element is not on the left flow")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Register a element define to be drawn to the relative flow on join
|
--- Register a element define to be drawn to the relative flow on join
|
||||||
@@ -119,14 +119,7 @@ end
|
|||||||
--- @param player LuaPlayer
|
--- @param player LuaPlayer
|
||||||
--- @return LuaGuiElement
|
--- @return LuaGuiElement
|
||||||
function ExpGui.get_relative_element(define, player)
|
function ExpGui.get_relative_element(define, player)
|
||||||
return player_elements[player.index].relative[define.name]
|
return assert(player_elements[player.index].relative[define.name], "Element is not on the relative flow")
|
||||||
end
|
|
||||||
|
|
||||||
--- Return all top level elements for a player
|
|
||||||
---@param player LuaPlayer
|
|
||||||
---@return ExpGui.player_elements
|
|
||||||
function ExpGui._get_player_elements(player)
|
|
||||||
return player_elements[player.index]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Ensure all the correct elements are visible and exist
|
--- Ensure all the correct elements are visible and exist
|
||||||
@@ -177,10 +170,10 @@ function ExpGui._ensure_elements(event)
|
|||||||
ensure_elements(player, ExpGui.left_elements, elements.left, ExpGui.get_left_flow(player))
|
ensure_elements(player, ExpGui.left_elements, elements.left, ExpGui.get_left_flow(player))
|
||||||
ensure_elements(player, ExpGui.relative_elements, elements.relative, player.gui.relative)
|
ensure_elements(player, ExpGui.relative_elements, elements.relative, player.gui.relative)
|
||||||
|
|
||||||
-- Check technically not needed, but makes it easier to use this lib without the core defines
|
--- @diagnostic disable-next-line invisible
|
||||||
if ExpGui.apply_consistency_checks then
|
ExpGui.toolbar._ensure_elements(player)
|
||||||
ExpGui.apply_consistency_checks(player, true)
|
--- @diagnostic disable-next-line invisible
|
||||||
end
|
ExpGui.toolbar._ensure_consistency(player)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Rerun the visible check for relative elements
|
--- Rerun the visible check for relative elements
|
||||||
|
|||||||
@@ -1,306 +0,0 @@
|
|||||||
|
|
||||||
--- @class ExpGui
|
|
||||||
local ExpGui = require("modules/exp_gui")
|
|
||||||
local mod_gui = require("mod-gui")
|
|
||||||
|
|
||||||
local toolbar_button_default_style = mod_gui.button_style
|
|
||||||
local toolbar_button_active_style = "menu_button_continue"
|
|
||||||
local toolbar_button_size = 36
|
|
||||||
|
|
||||||
local elements = {} --- @type table<string, ExpElement>
|
|
||||||
local buttons_with_left_element = {} --- @type table<string, ExpElement>
|
|
||||||
local left_elements_with_button = {} --- @type table<string, ExpElement>
|
|
||||||
|
|
||||||
ExpGui.on_toolbar_button_toggled = script.generate_event_name()
|
|
||||||
|
|
||||||
--- @class EventData.on_toolbar_button_toggled: EventData
|
|
||||||
--- @field element LuaGuiElement
|
|
||||||
--- @field state boolean
|
|
||||||
|
|
||||||
--- Set the style of a toolbar button
|
|
||||||
--- @param element LuaGuiElement
|
|
||||||
--- @param state boolean?
|
|
||||||
--- @return boolean
|
|
||||||
function ExpGui.set_toolbar_button_style(element, state)
|
|
||||||
if state == nil then state = element.style.name == toolbar_button_default_style end
|
|
||||||
element.style = state and toolbar_button_active_style or toolbar_button_default_style
|
|
||||||
|
|
||||||
local style = element.style
|
|
||||||
style.minimal_width = toolbar_button_size
|
|
||||||
style.height = toolbar_button_size
|
|
||||||
if element.type == "sprite-button" then
|
|
||||||
style.padding = -2
|
|
||||||
else
|
|
||||||
style.font = "default-semibold"
|
|
||||||
style.padding = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
return state
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the state of a toolbar button
|
|
||||||
--- @param element LuaGuiElement
|
|
||||||
--- @return boolean
|
|
||||||
function ExpGui.get_toolbar_button_state(element)
|
|
||||||
return element.style.name == toolbar_button_active_style
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the visible state of the top flow for a player
|
|
||||||
--- @param player LuaPlayer
|
|
||||||
--- @param state boolean?
|
|
||||||
function ExpGui.set_top_flow_visible(player, state)
|
|
||||||
local top_flow = assert(ExpGui.get_top_flow(player).parent, player.name)
|
|
||||||
local show_top_flow = elements.core_button_flow.data[player].show_top_flow --- @type LuaGuiElement
|
|
||||||
|
|
||||||
if state == nil then
|
|
||||||
state = not top_flow.visible
|
|
||||||
end
|
|
||||||
|
|
||||||
top_flow.visible = state
|
|
||||||
show_top_flow.visible = not state
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the visible state of the left element for a player
|
|
||||||
--- @param define ExpElement
|
|
||||||
--- @param player LuaPlayer
|
|
||||||
--- @param state boolean?
|
|
||||||
function ExpGui.set_left_element_visible(define, player, state)
|
|
||||||
local element = assert(ExpGui.get_left_element(define, player), "Define is not added to the left flow")
|
|
||||||
local clear_left_flow = elements.core_button_flow.data[player].clear_left_flow --- @type LuaGuiElement
|
|
||||||
|
|
||||||
-- Update the visible state
|
|
||||||
if state == nil then state = not element.visible end
|
|
||||||
element.visible = state
|
|
||||||
|
|
||||||
-- Check if there is a toolbar button linked to this element
|
|
||||||
local toolbar_button = left_elements_with_button[define.name]
|
|
||||||
if toolbar_button then
|
|
||||||
ExpGui.set_toolbar_button_style(ExpGui.get_top_element(toolbar_button, player), state)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If visible state is true, then we don't need to check all elements
|
|
||||||
if state then
|
|
||||||
clear_left_flow.visible = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if any left elements are visible
|
|
||||||
--- @diagnostic disable-next-line invisible
|
|
||||||
local player_elements = ExpGui._get_player_elements(player)
|
|
||||||
local flow_name = elements.core_button_flow.name
|
|
||||||
for name, left_element in pairs(player_elements.left) do
|
|
||||||
if left_element.visible and name ~= flow_name then
|
|
||||||
clear_left_flow.visible = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- There are no visible left elements, so can hide the button
|
|
||||||
clear_left_flow.visible = false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @class ExpGui.create_toolbar_button__param: LuaGuiElement.add_param.sprite_button, LuaGuiElement.add_param.button
|
|
||||||
--- @field name string
|
|
||||||
--- @field type nil
|
|
||||||
--- @field left_element ExpElement| nil
|
|
||||||
--- @field visible ExpGui.VisibleCallback | boolean | nil
|
|
||||||
|
|
||||||
--- Create a toolbar button
|
|
||||||
--- @param options ExpGui.create_toolbar_button__param
|
|
||||||
--- @return ExpElement
|
|
||||||
function ExpGui.create_toolbar_button(options)
|
|
||||||
-- Extract the custom options from the element.add options
|
|
||||||
local name = assert(options.name, "Name is required for the element")
|
|
||||||
options.type = options.sprite ~= nil and "sprite-button" or "button"
|
|
||||||
|
|
||||||
local visible = options.visible
|
|
||||||
if visible == nil then visible = true end
|
|
||||||
options.visible = nil
|
|
||||||
|
|
||||||
local auto_toggle = options.auto_toggle
|
|
||||||
options.auto_toggle = nil
|
|
||||||
|
|
||||||
local left_element = options.left_element
|
|
||||||
options.left_element = nil
|
|
||||||
|
|
||||||
if options.style == nil then
|
|
||||||
options.style = toolbar_button_default_style
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create the new element define
|
|
||||||
local toolbar_button = ExpGui.element(name)
|
|
||||||
:draw(options)
|
|
||||||
:style{
|
|
||||||
minimal_width = toolbar_button_size,
|
|
||||||
height = toolbar_button_size,
|
|
||||||
padding = options.sprite ~= nil and -2 or nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- If a left element was given then link the define
|
|
||||||
if left_element then
|
|
||||||
left_elements_with_button[left_element.name] = toolbar_button
|
|
||||||
buttons_with_left_element[toolbar_button.name] = left_element
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Setup auto toggle, required if there is a left element
|
|
||||||
if auto_toggle or left_element then
|
|
||||||
toolbar_button:on_click(function(def, event)
|
|
||||||
local state = ExpGui.set_toolbar_button_style(event.element)
|
|
||||||
if left_element then
|
|
||||||
local player = ExpGui.get_player(event)
|
|
||||||
ExpGui.set_left_element_visible(left_element, player, state)
|
|
||||||
end
|
|
||||||
script.raise_event(ExpGui.on_toolbar_button_toggled, {
|
|
||||||
element = event.element,
|
|
||||||
state = state,
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add the define to the top flow and return
|
|
||||||
ExpGui.add_top_element(toolbar_button, visible)
|
|
||||||
return toolbar_button
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Update the consistency of the core elements and registered elements
|
|
||||||
--- @param player LuaPlayer
|
|
||||||
--- @param skip_ensure boolean?
|
|
||||||
function ExpGui.apply_consistency_checks(player, skip_ensure)
|
|
||||||
if not skip_ensure then
|
|
||||||
--- @diagnostic disable-next-line invisible
|
|
||||||
ExpGui._ensure_elements{ player_index = player.index }
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get the core buttons for the player
|
|
||||||
local core_button_data = elements.core_button_flow.data[player]
|
|
||||||
local hide_top_flow = ExpGui.get_top_element(elements.hide_top_flow, player)
|
|
||||||
local show_top_flow = core_button_data.show_top_flow --- @type LuaGuiElement
|
|
||||||
local clear_left_flow = core_button_data.clear_left_flow --- @type LuaGuiElement
|
|
||||||
|
|
||||||
-- Check if any top elements are visible, this includes ones not controlled by this module
|
|
||||||
local has_top_elements = false
|
|
||||||
local top_flow = ExpGui.get_top_flow(player)
|
|
||||||
for _, element in pairs(top_flow.children) do
|
|
||||||
if element.visible and element ~= hide_top_flow then
|
|
||||||
has_top_elements = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The show button is only visible when the flow isn't visible but does have visible children
|
|
||||||
show_top_flow.visible = has_top_elements and not top_flow.visible or false
|
|
||||||
|
|
||||||
--- @diagnostic disable-next-line invisible
|
|
||||||
local player_elements = ExpGui._get_player_elements(player)
|
|
||||||
local left_elements, top_elements = player_elements.left, player_elements.top
|
|
||||||
|
|
||||||
--- Update the styles of toolbar buttons with left elements
|
|
||||||
for name, top_element in pairs(top_elements) do
|
|
||||||
local left_element = buttons_with_left_element[name]
|
|
||||||
if left_element then
|
|
||||||
local element = assert(left_elements[left_element.name], left_element.name)
|
|
||||||
ExpGui.set_toolbar_button_style(top_element, element.visible)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if any left elements are visible
|
|
||||||
local flow_name = elements.core_button_flow.name
|
|
||||||
for name, left_element in pairs(left_elements) do
|
|
||||||
if left_element.visible and name ~= flow_name then
|
|
||||||
clear_left_flow.visible = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- There are no visible left elements, so can hide the button
|
|
||||||
clear_left_flow.visible = false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Hides the top flow when clicked
|
|
||||||
elements.hide_top_flow = ExpGui.element("hide_top_flow")
|
|
||||||
:draw{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/preset",
|
|
||||||
style = "tool_button",
|
|
||||||
tooltip = { "exp-gui.hide-top-flow" },
|
|
||||||
}
|
|
||||||
:style{
|
|
||||||
padding = -2,
|
|
||||||
width = 18,
|
|
||||||
height = 36,
|
|
||||||
}
|
|
||||||
:on_click(function(def, event)
|
|
||||||
local player = ExpGui.get_player(event)
|
|
||||||
ExpGui.set_top_flow_visible(player, false)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Shows the top flow when clicked
|
|
||||||
elements.show_top_flow = ExpGui.element("show_top_flow")
|
|
||||||
:draw{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/preset",
|
|
||||||
style = "tool_button",
|
|
||||||
tooltip = { "exp-gui.show-top-flow" },
|
|
||||||
}
|
|
||||||
:style{
|
|
||||||
padding = -2,
|
|
||||||
width = 18,
|
|
||||||
height = 20,
|
|
||||||
}
|
|
||||||
:on_click(function(def, event)
|
|
||||||
local player = ExpGui.get_player(event)
|
|
||||||
ExpGui.set_top_flow_visible(player, true)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Hides all left elements when clicked
|
|
||||||
elements.clear_left_flow = ExpGui.element("clear_left_flow")
|
|
||||||
:draw{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/close_black",
|
|
||||||
style = "tool_button",
|
|
||||||
tooltip = { "exp-gui.clear-left-flow" },
|
|
||||||
}
|
|
||||||
:style{
|
|
||||||
padding = -3,
|
|
||||||
width = 18,
|
|
||||||
height = 20,
|
|
||||||
}
|
|
||||||
:on_click(function(def, event)
|
|
||||||
local player = ExpGui.get_player(event)
|
|
||||||
event.element.visible = false
|
|
||||||
|
|
||||||
--- @diagnostic disable-next-line invisible
|
|
||||||
local player_elements = ExpGui._get_player_elements(player)
|
|
||||||
local flow_name = elements.core_button_flow.name
|
|
||||||
for name, left_element in pairs(player_elements.left) do
|
|
||||||
if name ~= flow_name then
|
|
||||||
left_element.visible = false
|
|
||||||
local toolbar_button = left_elements_with_button[name]
|
|
||||||
if toolbar_button then
|
|
||||||
ExpGui.set_toolbar_button_style(ExpGui.get_top_element(toolbar_button, player), false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Contains the two buttons on the left flow
|
|
||||||
elements.core_button_flow = ExpGui.element("core_button_flow")
|
|
||||||
:draw(function(def, parent)
|
|
||||||
local flow = parent.add{
|
|
||||||
type = "flow",
|
|
||||||
direction = "vertical",
|
|
||||||
}
|
|
||||||
|
|
||||||
local player = ExpGui.get_player(parent)
|
|
||||||
def.data[player] = {
|
|
||||||
show_top_flow = elements.show_top_flow(flow),
|
|
||||||
clear_left_flow = elements.clear_left_flow(flow),
|
|
||||||
}
|
|
||||||
|
|
||||||
return flow
|
|
||||||
end)
|
|
||||||
|
|
||||||
ExpGui.add_top_element(elements.hide_top_flow, true)
|
|
||||||
ExpGui.add_left_element(elements.core_button_flow, true)
|
|
||||||
|
|
||||||
return elements
|
|
||||||
@@ -6,7 +6,7 @@ local ExpUtil = require("modules/exp_util")
|
|||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
|
|
||||||
--- @alias ExpGui_GuiIter.FilterType LuaPlayer | LuaForce | LuaPlayer[] | nil
|
--- @alias ExpGui_GuiIter.FilterType LuaPlayer | LuaForce | LuaPlayer[] | nil
|
||||||
--- @alias ExpGui_GuiIter.ReturnType ExpGui_GuiIter.ReturnType
|
--- @alias ExpGui_GuiIter.ReturnType fun(): LuaPlayer?, LuaGuiElement?
|
||||||
|
|
||||||
--- @type table<string, table<uint, table<uint, LuaGuiElement>>>
|
--- @type table<string, table<uint, table<uint, LuaGuiElement>>>
|
||||||
local registered_scopes = {}
|
local registered_scopes = {}
|
||||||
@@ -25,6 +25,7 @@ end)
|
|||||||
|
|
||||||
--- @class ExpGui_GuiIter
|
--- @class ExpGui_GuiIter
|
||||||
local GuiIter = {
|
local GuiIter = {
|
||||||
|
_scopes = registered_scopes,
|
||||||
}
|
}
|
||||||
|
|
||||||
local function nop() return nil, nil end
|
local function nop() return nil, nil end
|
||||||
@@ -215,10 +216,10 @@ function GuiIter.add_element(scope, element)
|
|||||||
registered_scopes[scope] = scope_elements
|
registered_scopes[scope] = scope_elements
|
||||||
end
|
end
|
||||||
|
|
||||||
local player_elements = registered_scopes[element.player_index]
|
local player_elements = scope_elements[element.player_index]
|
||||||
if not player_elements then
|
if not player_elements then
|
||||||
player_elements = {}
|
player_elements = {}
|
||||||
registered_scopes[element.player_index] = player_elements
|
scope_elements[element.player_index] = player_elements
|
||||||
end
|
end
|
||||||
|
|
||||||
player_elements[element.index] = element
|
player_elements[element.index] = element
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
|
|
||||||
[exp-gui]
|
[exp-gui]
|
||||||
hide-top-flow=Hide Toolbar.
|
clear-left-flow=Hide all open windows.
|
||||||
show-top-flow=Show Toolbar.
|
close-toolbar=__CONTROL_LEFT_CLICK__: Toggle Settings\n__CONTROL_RIGHT_CLICK__: Close Toolbar
|
||||||
clear-left-flow=Hide all open windows.
|
open-toolbar=__CONTROL_LEFT_CLICK__: Toggle Settings\n__CONTROL_RIGHT_CLICK__: Open Toolbar
|
||||||
|
|
||||||
|
[exp-gui_toolbar-settings]
|
||||||
|
main-caption=Toolbox
|
||||||
|
main-tooltip=Toolbox Settings\nUse the checkboxes to select favourites
|
||||||
|
reset=Reset All
|
||||||
|
toggle=Toggle Favourites
|
||||||
|
move-up=Move Up
|
||||||
|
move-down=Move Down
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
"control.lua"
|
"control.lua"
|
||||||
],
|
],
|
||||||
"require": [
|
"require": [
|
||||||
"core_elements.lua",
|
|
||||||
"elements.lua",
|
"elements.lua",
|
||||||
"styles.lua"
|
"styles.lua",
|
||||||
|
"toolbar.lua"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clusterio": "*",
|
"clusterio": "*",
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ function ExpElement.create(name)
|
|||||||
data = GuiData.create(element_name),
|
data = GuiData.create(element_name),
|
||||||
_events = {},
|
_events = {},
|
||||||
_debug = {
|
_debug = {
|
||||||
defined_at = ExpUtil.safe_file_path(2),
|
defined_at = ExpUtil.get_current_line(2),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +106,13 @@ function ExpElement.create(name)
|
|||||||
return setmetatable(instance, ExpElement._metatable)
|
return setmetatable(instance, ExpElement._metatable)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get an element by its name
|
||||||
|
--- @param name string
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement.get(name)
|
||||||
|
return assert(ExpElement._elements[name], "ExpElement is not defined: " .. tostring(name))
|
||||||
|
end
|
||||||
|
|
||||||
--- Create a new instance of this element definition
|
--- Create a new instance of this element definition
|
||||||
--- @param parent LuaGuiElement
|
--- @param parent LuaGuiElement
|
||||||
--- @param ... any
|
--- @param ... any
|
||||||
@@ -179,6 +186,15 @@ function ExpElement._prototype:track_all_elements()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add a temp draw definition, useful for when working top down
|
||||||
|
--- @return ExpElement
|
||||||
|
function ExpElement._prototype:dev()
|
||||||
|
log("Dev draw used for " .. self.name)
|
||||||
|
return self:draw{
|
||||||
|
type = "flow"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
--- @alias ExpElement.add_param LuaGuiElement.add_param | table<string, [function, number|string|nil] | function>
|
--- @alias ExpElement.add_param LuaGuiElement.add_param | table<string, [function, number|string|nil] | function>
|
||||||
|
|
||||||
--- Set the draw definition
|
--- Set the draw definition
|
||||||
|
|||||||
714
exp_gui/module/toolbar.lua
Normal file
714
exp_gui/module/toolbar.lua
Normal file
@@ -0,0 +1,714 @@
|
|||||||
|
|
||||||
|
--- @class ExpGui
|
||||||
|
local ExpGui = require("modules/exp_gui")
|
||||||
|
local ExpElement = require("modules/exp_gui/prototype")
|
||||||
|
local mod_gui = require("mod-gui")
|
||||||
|
|
||||||
|
local toolbar_button_default_style = mod_gui.button_style
|
||||||
|
local toolbar_button_active_style = "menu_button_continue"
|
||||||
|
local toolbar_button_size = 36
|
||||||
|
local toolbar_button_small = 20
|
||||||
|
|
||||||
|
--- @class ExpGui.toolbar
|
||||||
|
local Toolbar = {}
|
||||||
|
ExpGui.toolbar = Toolbar
|
||||||
|
|
||||||
|
local elements = {}
|
||||||
|
Toolbar.elements = elements
|
||||||
|
|
||||||
|
local left_elements_with_button = {} --- @type table<ExpElement, ExpElement>
|
||||||
|
local buttons_with_left_element = {} --- @type table<string, ExpElement>
|
||||||
|
|
||||||
|
--- Set the visible state of the toolbar
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @param state boolean? toggles if nil
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.set_visible_state(player, state)
|
||||||
|
-- Update the top flow
|
||||||
|
local top_flow = assert(ExpGui.get_top_flow(player).parent)
|
||||||
|
if state == nil then state = not top_flow.visible end
|
||||||
|
top_flow.visible = state
|
||||||
|
|
||||||
|
-- Update the open toolbar button
|
||||||
|
for _, open_toolbar in elements.open_toolbar:tracked_elements(player) do
|
||||||
|
open_toolbar.visible = not state
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update the toggle toolbar button
|
||||||
|
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||||
|
toggle_toolbar.toggled = state
|
||||||
|
end
|
||||||
|
|
||||||
|
return state
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the visible state of the toolbar
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.get_visible_state(player)
|
||||||
|
local top_flow = assert(ExpGui.get_top_flow(player).parent)
|
||||||
|
return top_flow.visible
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the toggle state of a toolbar button, does not check for a linked left element
|
||||||
|
--- @param define ExpElement
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @param state boolean? toggles if nil
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.set_button_toggled_state(define, player, state)
|
||||||
|
local top_element = assert(ExpGui.get_top_element(define, player), "Element is not on the top flow")
|
||||||
|
if state == nil then state = top_element.style.name == toolbar_button_default_style end
|
||||||
|
|
||||||
|
for _, element in define:tracked_elements(player) do
|
||||||
|
local original_width, original_height = element.style.minimal_width, element.style.maximal_height
|
||||||
|
element.style = state and toolbar_button_active_style or toolbar_button_default_style
|
||||||
|
|
||||||
|
-- Make the extra required adjustments
|
||||||
|
local style = element.style
|
||||||
|
style.minimal_width = original_width
|
||||||
|
style.maximal_height = original_height
|
||||||
|
if element.type == "sprite-button" then
|
||||||
|
style.padding = -2
|
||||||
|
else
|
||||||
|
style.font = "default-semibold"
|
||||||
|
style.padding = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return state
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the toggle state of a toolbar button
|
||||||
|
--- @param define ExpElement
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.get_button_toggled_state(define, player)
|
||||||
|
local element = assert(ExpGui.get_top_element(define, player), "Element is not on the top flow")
|
||||||
|
return element.style.name == toolbar_button_active_style
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the visible state of a left element
|
||||||
|
--- @param define ExpElement
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @param state boolean? toggles if nil
|
||||||
|
--- @param _skip_consistency boolean?
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.set_left_element_visible_state(define, player, state, _skip_consistency)
|
||||||
|
local element = assert(ExpGui.get_left_element(define, player), "Element is not on the left flow")
|
||||||
|
if state == nil then state = not element.visible end
|
||||||
|
element.visible = state
|
||||||
|
|
||||||
|
-- Check if there is a linked toolbar button and update it
|
||||||
|
local button = left_elements_with_button[define]
|
||||||
|
if button then
|
||||||
|
Toolbar.set_button_toggled_state(button, player, state)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This check is O(n^2) when setting all left elements to hidden, so internals can it
|
||||||
|
if _skip_consistency then return state end
|
||||||
|
|
||||||
|
-- Update the clear left flow button, visible when at least one element is visible
|
||||||
|
local has_visible = Toolbar.has_visible_left_elements(player)
|
||||||
|
for _, clear_left_flow in elements.clear_left_flow:tracked_elements(player) do
|
||||||
|
clear_left_flow.visible = state or has_visible
|
||||||
|
end
|
||||||
|
|
||||||
|
return state
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the toggle state of a left element
|
||||||
|
--- @param define ExpElement
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.get_left_element_visible_state(define, player)
|
||||||
|
local element = assert(ExpGui.get_left_element(define, player), "Element is not on the left flow")
|
||||||
|
return element.visible
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if there are any visible toolbar buttons
|
||||||
|
--- @param player any
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.has_visible_buttons(player)
|
||||||
|
local top_flow = ExpGui.get_top_flow(player)
|
||||||
|
local settings_button = ExpGui.get_top_element(elements.close_toolbar, player)
|
||||||
|
|
||||||
|
for _, element in pairs(top_flow.children) do
|
||||||
|
if element.visible and element ~= settings_button then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if there are any visible left elements
|
||||||
|
--- @param player any
|
||||||
|
--- @return boolean
|
||||||
|
function Toolbar.has_visible_left_elements(player)
|
||||||
|
local left_flow = ExpGui.get_left_flow(player)
|
||||||
|
local core_button_flow = ExpGui.get_left_element(elements.core_button_flow, player)
|
||||||
|
|
||||||
|
for _, element in pairs(left_flow.children) do
|
||||||
|
if element.visible and element ~= core_button_flow then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @class ExpGui.toolbar.create_button__param: LuaGuiElement.add_param.sprite_button, LuaGuiElement.add_param.button
|
||||||
|
--- @field name string
|
||||||
|
--- @field type nil
|
||||||
|
--- @field left_element ExpElement| nil
|
||||||
|
--- @field visible ExpGui.VisibleCallback | boolean | nil
|
||||||
|
|
||||||
|
--- Create a toolbar button
|
||||||
|
--- @param options ExpGui.toolbar.create_button__param
|
||||||
|
--- @return ExpElement
|
||||||
|
function Toolbar.create_button(options)
|
||||||
|
-- Extract the custom options from the element.add options
|
||||||
|
local name = assert(options.name, "Name is required for the element")
|
||||||
|
options.type = options.sprite ~= nil and "sprite-button" or "button"
|
||||||
|
|
||||||
|
local visible = options.visible
|
||||||
|
if visible == nil then visible = true end
|
||||||
|
options.visible = nil
|
||||||
|
|
||||||
|
local auto_toggle = options.auto_toggle
|
||||||
|
options.auto_toggle = nil
|
||||||
|
|
||||||
|
local left_element = options.left_element
|
||||||
|
options.left_element = nil
|
||||||
|
|
||||||
|
if options.style == nil then
|
||||||
|
options.style = toolbar_button_default_style
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the new element define
|
||||||
|
local toolbar_button = ExpGui.element(name)
|
||||||
|
:track_all_elements()
|
||||||
|
:draw(options)
|
||||||
|
:style{
|
||||||
|
minimal_width = toolbar_button_size,
|
||||||
|
height = toolbar_button_size,
|
||||||
|
padding = options.sprite ~= nil and -2 or nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- If a left element was given then link the define
|
||||||
|
if left_element then
|
||||||
|
left_elements_with_button[left_element] = toolbar_button
|
||||||
|
buttons_with_left_element[toolbar_button.name] = left_element
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Setup auto toggle, required if there is a left element
|
||||||
|
if auto_toggle or left_element then
|
||||||
|
toolbar_button:on_click(function(def, event)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
if left_element then
|
||||||
|
Toolbar.set_left_element_visible_state(left_element, player)
|
||||||
|
else
|
||||||
|
Toolbar.set_button_toggled_state(toolbar_button, player)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add the define to the top flow and return
|
||||||
|
ExpGui.add_top_element(toolbar_button, visible)
|
||||||
|
return toolbar_button
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Ensure all the toolbar buttons are in a consistent state
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
function Toolbar._ensure_consistency(player)
|
||||||
|
-- Update clear_left_flow
|
||||||
|
local has_visible = Toolbar.has_visible_left_elements(player)
|
||||||
|
for _, clear_left_flow in elements.clear_left_flow:tracked_elements(player) do
|
||||||
|
clear_left_flow.visible = has_visible
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update open_toolbar
|
||||||
|
local top_flow = assert(ExpGui.get_top_flow(player).parent)
|
||||||
|
for _, open_toolbar in elements.open_toolbar:tracked_elements(player) do
|
||||||
|
open_toolbar.visible = not top_flow.visible
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update toggle_toolbar
|
||||||
|
local has_buttons = Toolbar.has_visible_buttons(player)
|
||||||
|
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||||
|
toggle_toolbar.enabled = has_buttons
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update the state of buttons with left elements
|
||||||
|
for left_element, button in pairs(left_elements_with_button) do
|
||||||
|
local element = ExpGui.get_left_element(left_element, player)
|
||||||
|
Toolbar.set_button_toggled_state(button, player, element.visible)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Toggles the toolbar settings, RMB will instead hide the toolbar
|
||||||
|
elements.close_toolbar = ExpGui.element("close_toolbar")
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/preset",
|
||||||
|
style = "tool_button",
|
||||||
|
tooltip = { "exp-gui.close-toolbar" },
|
||||||
|
}
|
||||||
|
:style{
|
||||||
|
padding = -2,
|
||||||
|
width = 18,
|
||||||
|
height = 36,
|
||||||
|
}
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
if event.button == defines.mouse_button_type.left then
|
||||||
|
Toolbar.set_left_element_visible_state(elements.toolbar_settings, player)
|
||||||
|
else
|
||||||
|
Toolbar.set_visible_state(player, false)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Shows the toolbar, if no buttons are visible then it shows the settings instead
|
||||||
|
elements.open_toolbar = ExpGui.element("open_toolbar")
|
||||||
|
:track_all_elements()
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/preset",
|
||||||
|
style = "tool_button",
|
||||||
|
tooltip = { "exp-gui.open-toolbar" },
|
||||||
|
}
|
||||||
|
:style{
|
||||||
|
padding = -2,
|
||||||
|
width = 18,
|
||||||
|
height = 20,
|
||||||
|
}
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
if event.button == defines.mouse_button_type.left then
|
||||||
|
Toolbar.set_left_element_visible_state(elements.toolbar_settings, player)
|
||||||
|
else
|
||||||
|
Toolbar.set_visible_state(player, true)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Hides all left elements when clicked
|
||||||
|
elements.clear_left_flow = ExpGui.element("clear_left_flow")
|
||||||
|
:track_all_elements()
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/close_black",
|
||||||
|
style = "tool_button",
|
||||||
|
tooltip = { "exp-gui.clear-left-flow" },
|
||||||
|
}
|
||||||
|
:style{
|
||||||
|
padding = -3,
|
||||||
|
width = 18,
|
||||||
|
height = 20,
|
||||||
|
}
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
element.visible = false
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
for define in pairs(ExpGui.left_elements) do
|
||||||
|
if define ~= elements.core_button_flow then
|
||||||
|
Toolbar.set_left_element_visible_state(define, player, false, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Contains the two buttons on the left flow
|
||||||
|
elements.core_button_flow = ExpGui.element("core_button_flow")
|
||||||
|
:draw(function(def, parent)
|
||||||
|
local flow = parent.add{
|
||||||
|
type = "flow",
|
||||||
|
direction = "vertical",
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.open_toolbar(flow)
|
||||||
|
elements.clear_left_flow(flow)
|
||||||
|
|
||||||
|
return flow
|
||||||
|
end)
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Below here is the toolbar settings GUI and its associated functions
|
||||||
|
]]
|
||||||
|
|
||||||
|
--- Set the style of the fake toolbar element
|
||||||
|
--- @param src LuaGuiElement
|
||||||
|
--- @param dst LuaGuiElement
|
||||||
|
local function copy_style(src, dst)
|
||||||
|
dst.style = src.style.name
|
||||||
|
dst.style.height = toolbar_button_small
|
||||||
|
dst.style.width = toolbar_button_small
|
||||||
|
dst.style.padding = -2
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Reorder the buttons relative to each other, this will update the datastore
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @param item LuaGuiElement
|
||||||
|
--- @param offset number
|
||||||
|
local function move_toolbar_button(player, item, offset)
|
||||||
|
local old_index = item.get_index_in_parent()
|
||||||
|
local new_index = old_index + offset
|
||||||
|
|
||||||
|
-- Swap the position in the list
|
||||||
|
local list = assert(item.parent)
|
||||||
|
local other_item = list.children[new_index]
|
||||||
|
list.swap_children(old_index, new_index)
|
||||||
|
|
||||||
|
-- Swap the position in the top flow, offset by 1 because of settings button
|
||||||
|
local top_flow = ExpGui.get_top_flow(player)
|
||||||
|
top_flow.swap_children(old_index + 1, new_index + 1)
|
||||||
|
|
||||||
|
-- Check if the element has a left element to move
|
||||||
|
local left_element = buttons_with_left_element[item.name]
|
||||||
|
local other_left_element = buttons_with_left_element[other_item.name]
|
||||||
|
if left_element and other_left_element then
|
||||||
|
local element = ExpGui.get_left_element(left_element, player)
|
||||||
|
local other_element = ExpGui.get_left_element(other_left_element, player)
|
||||||
|
local left_index = element.get_index_in_parent()
|
||||||
|
local other_index = other_element.get_index_in_parent()
|
||||||
|
element.parent.swap_children(left_index, other_index)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If we are moving in/out of first/last place we need to update the move buttons
|
||||||
|
local last_index = #list.children
|
||||||
|
local item_data = elements.toolbar_list_item.data[item]
|
||||||
|
local other_item_data = elements.toolbar_list_item.data[other_item]
|
||||||
|
if old_index == 1 then -- Moving out of index 1
|
||||||
|
item_data.move_item_up.enabled = true
|
||||||
|
other_item_data.move_item_up.enabled = false
|
||||||
|
elseif new_index == 1 then -- Moving into index 1
|
||||||
|
item_data.move_item_up.enabled = false
|
||||||
|
other_item_data.move_item_up.enabled = true
|
||||||
|
elseif old_index == last_index then -- Moving out of the last index
|
||||||
|
item_data.move_item_down.enabled = true
|
||||||
|
other_item_data.move_item_down.enabled = false
|
||||||
|
elseif new_index == last_index then -- Moving into the last index
|
||||||
|
item_data.move_item_down.enabled = false
|
||||||
|
other_item_data.move_item_down.enabled = true
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[ Update the datastore state
|
||||||
|
ToolbarState:update(player, function(_, order)
|
||||||
|
local tmp = order[old_index]
|
||||||
|
order[old_index] = order[new_index]
|
||||||
|
order[new_index] = tmp
|
||||||
|
end)]]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @alias ExpGui.ToolbarOrder { name: string, favourite: boolean }[]
|
||||||
|
|
||||||
|
--- Reorder the toolbar buttons
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @param order ExpGui.ToolbarOrder
|
||||||
|
function Toolbar.set_order(player, order)
|
||||||
|
local list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]]
|
||||||
|
local top_flow = ExpGui.get_top_flow(player)
|
||||||
|
|
||||||
|
-- Reorder the buttons
|
||||||
|
local last_index = #order
|
||||||
|
for index, item_state in ipairs(order) do
|
||||||
|
-- Switch item order
|
||||||
|
local item = assert(list[item_state.name], "Missing toolbox item for " .. tostring(item_state.name))
|
||||||
|
list.swap_children(index, item.get_index_in_parent())
|
||||||
|
|
||||||
|
-- Update the item visibility
|
||||||
|
local element_define = ExpElement.get(item_state.name)
|
||||||
|
local allowed = ExpGui.top_elements[element_define]
|
||||||
|
local toolbar_button = ExpGui.get_top_element(element_define, player)
|
||||||
|
if type(allowed) == "function" then allowed = allowed(player, toolbar_button) end
|
||||||
|
top_flow.swap_children(index + 1, toolbar_button.get_index_in_parent())
|
||||||
|
toolbar_button.visible = allowed and item_state.favourite or false
|
||||||
|
item.visible = toolbar_button.visible
|
||||||
|
|
||||||
|
-- Update the children buttons
|
||||||
|
local data = elements.toolbar_list_item.data[item]
|
||||||
|
data.set_favourite.state = item_state.favourite
|
||||||
|
data.move_item_up.enabled = index ~= 1
|
||||||
|
data.move_item_down.enabled = index ~= last_index
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update the state of the toggle button
|
||||||
|
local has_buttons = Toolbar.has_visible_buttons(player)
|
||||||
|
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||||
|
toggle_toolbar.enabled = has_buttons
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @class (exact) ExpGui.ToolbarState
|
||||||
|
--- @field order ExpGui.ToolbarOrder
|
||||||
|
--- @field open string[]
|
||||||
|
--- @field visible boolean
|
||||||
|
|
||||||
|
--- Reorder the toolbar buttons and set the open state of the left flows
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
--- @param state ExpGui.ToolbarState
|
||||||
|
function Toolbar.set_state(player, state)
|
||||||
|
Toolbar.set_order(player, state.order)
|
||||||
|
Toolbar.set_visible_state(player, state.visible)
|
||||||
|
|
||||||
|
local done = {}
|
||||||
|
-- Make all open elements visible
|
||||||
|
for _, name in pairs(state.open) do
|
||||||
|
local left_element = ExpElement.get(name)
|
||||||
|
Toolbar.set_left_element_visible_state(left_element, player, true, true)
|
||||||
|
done[left_element] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Make all other elements hidden
|
||||||
|
for left_element in pairs(ExpGui.left_elements) do
|
||||||
|
if not done[left_element] then
|
||||||
|
Toolbar.set_left_element_visible_state(left_element, player, false, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update clear_left_flow (because we skip above)
|
||||||
|
local has_visible = Toolbar.has_visible_left_elements(player)
|
||||||
|
for _, clear_left_flow in elements.clear_left_flow:tracked_elements(player) do
|
||||||
|
clear_left_flow.visible = has_visible
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Ensure the toolbar settings gui has all its elements
|
||||||
|
--- @param player LuaPlayer
|
||||||
|
function Toolbar._ensure_elements(player)
|
||||||
|
-- Add any missing items to the gui
|
||||||
|
local toolbar_list = elements.toolbar_settings.data[player] --[[ @as LuaGuiElement ]]
|
||||||
|
for define in pairs(ExpGui.top_elements) do
|
||||||
|
if define ~= elements.close_toolbar and toolbar_list[define.name] == nil then
|
||||||
|
local element = elements.toolbar_list_item(toolbar_list, define)
|
||||||
|
element.visible = ExpGui.get_top_element(define, player).visible
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the state of the move buttons for the first and last element
|
||||||
|
local children = toolbar_list.children
|
||||||
|
if #children > 0 then
|
||||||
|
elements.toolbar_list_item.data[children[1]].move_item_up.enabled = false
|
||||||
|
elements.toolbar_list_item.data[children[#children]].move_item_down.enabled = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local default_order --- @type ExpGui.ToolbarOrder
|
||||||
|
--- Gets the default order for the toolbar
|
||||||
|
--- @return ExpGui.ToolbarOrder
|
||||||
|
function Toolbar.get_default_order()
|
||||||
|
if default_order then return default_order end
|
||||||
|
|
||||||
|
local index = 1
|
||||||
|
default_order = {}
|
||||||
|
for define in pairs(ExpGui.top_elements) do
|
||||||
|
if define ~= elements.close_toolbar then
|
||||||
|
default_order[index] = { name = define.name, favourite = true }
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return default_order
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Toggle the visibility of the toolbar, does not care if buttons are visible
|
||||||
|
elements.toggle_toolbar = ExpGui.element("toggle_toolbar")
|
||||||
|
:track_all_elements()
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/bookmark",
|
||||||
|
tooltip = { "exp-gui_toolbar-settings.toggle" },
|
||||||
|
style = "tool_button",
|
||||||
|
auto_toggle = true,
|
||||||
|
}
|
||||||
|
:style(ExpGui.styles.sprite{
|
||||||
|
size = 22,
|
||||||
|
})
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
Toolbar.set_visible_state(player, element.toggled)
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Reset the toolbar to its default state
|
||||||
|
elements.reset_toolbar = ExpGui.element("reset_toolbar")
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/reset",
|
||||||
|
style = "shortcut_bar_button_red",
|
||||||
|
tooltip = { "exp-gui_toolbar-settings.reset" },
|
||||||
|
}
|
||||||
|
:style(ExpGui.styles.sprite{
|
||||||
|
size = 22,
|
||||||
|
padding = -1,
|
||||||
|
})
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
--ToolbarState:set(player, nil)
|
||||||
|
Toolbar.set_order(player, Toolbar.get_default_order())
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Move an item up/left on the toolbar
|
||||||
|
elements.move_item_up = ExpGui.element("move_item_up")
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/speed_up",
|
||||||
|
tooltip = { "exp-gui_toolbar-settings.move-up" },
|
||||||
|
}
|
||||||
|
:style(ExpGui.styles.sprite{
|
||||||
|
size = toolbar_button_small,
|
||||||
|
})
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
local item = assert(element.parent.parent)
|
||||||
|
move_toolbar_button(player, item, -1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Move an item down/right on the toolbar
|
||||||
|
elements.move_item_down = ExpGui.element("move_item_down")
|
||||||
|
:draw{
|
||||||
|
type = "sprite-button",
|
||||||
|
sprite = "utility/speed_down",
|
||||||
|
tooltip = { "exp-gui_toolbar-settings.move-down" },
|
||||||
|
}
|
||||||
|
:style(ExpGui.styles.sprite{
|
||||||
|
size = toolbar_button_small,
|
||||||
|
})
|
||||||
|
:on_click(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
local item = assert(element.parent.parent)
|
||||||
|
move_toolbar_button(player, item, 1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Set an item as a favourite, making it appear on the toolbar
|
||||||
|
elements.set_favourite = ExpGui.element("set_favourite")
|
||||||
|
:draw(function(def, parent, item_define)
|
||||||
|
--- @cast item_define ExpElement
|
||||||
|
local player = ExpGui.get_player(parent)
|
||||||
|
local top_element = ExpGui.get_top_element(item_define, player)
|
||||||
|
|
||||||
|
return parent.add{
|
||||||
|
type = "checkbox",
|
||||||
|
caption = top_element.tooltip or top_element.caption or nil,
|
||||||
|
state = top_element.visible or false,
|
||||||
|
tags = {
|
||||||
|
element_name = item_define.name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
:style{
|
||||||
|
width = 180,
|
||||||
|
}
|
||||||
|
:on_checked_state_changed(function(def, event, element)
|
||||||
|
local player = ExpGui.get_player(event)
|
||||||
|
local define = ExpElement.get(element.tags.element_name --[[ @as string ]])
|
||||||
|
local top_element = ExpGui.get_top_element(define, player)
|
||||||
|
local had_visible = Toolbar.has_visible_buttons(player)
|
||||||
|
top_element.visible = element.state
|
||||||
|
|
||||||
|
-- Check if we are on the edge case between 0 and 1 visible elements
|
||||||
|
if element.state and not had_visible then
|
||||||
|
Toolbar.set_visible_state(player, true)
|
||||||
|
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||||
|
toggle_toolbar.enabled = true
|
||||||
|
end
|
||||||
|
elseif not element.state and not Toolbar.has_visible_buttons(player) then
|
||||||
|
Toolbar.set_visible_state(player, false)
|
||||||
|
for _, toggle_toolbar in elements.toggle_toolbar:tracked_elements(player) do
|
||||||
|
toggle_toolbar.enabled = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[ Update the datastore state
|
||||||
|
ToolbarState:update(player, function(_, order)
|
||||||
|
local index = element.parent.get_index_in_parent()
|
||||||
|
order[index].favourite = element.state
|
||||||
|
end)]]
|
||||||
|
end)
|
||||||
|
|
||||||
|
elements.toolbar_list_item = ExpGui.element("toolbar_list_item")
|
||||||
|
:draw(function(def, parent, item_define)
|
||||||
|
--- @cast item_define ExpElement
|
||||||
|
local data = {}
|
||||||
|
|
||||||
|
-- Add the flow for the item
|
||||||
|
local flow = parent.add{
|
||||||
|
name = item_define.name,
|
||||||
|
type = "frame",
|
||||||
|
style = "shortcut_selection_row",
|
||||||
|
}
|
||||||
|
flow.style.horizontally_stretchable = true
|
||||||
|
flow.style.vertical_align = "center"
|
||||||
|
|
||||||
|
-- Add the button and the icon edit button
|
||||||
|
local element = item_define(flow)
|
||||||
|
local player = ExpGui.get_player(parent)
|
||||||
|
local top_element = ExpGui.get_top_element(item_define, player)
|
||||||
|
copy_style(top_element, element)
|
||||||
|
|
||||||
|
-- Add the favourite checkbox and label
|
||||||
|
data.set_favourite = elements.set_favourite(flow, item_define)
|
||||||
|
|
||||||
|
-- Add the buttons used to move the flow up and down
|
||||||
|
local move_flow = flow.add{ type = "flow", name = "move" }
|
||||||
|
move_flow.style.horizontal_spacing = 0
|
||||||
|
data.move_item_up = elements.move_item_up(move_flow)
|
||||||
|
data.move_item_down = elements.move_item_down(move_flow)
|
||||||
|
|
||||||
|
def.data[flow] = data
|
||||||
|
return flow
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Main list for all toolbar items
|
||||||
|
elements.toolbar_list = ExpGui.element("toolbar_list")
|
||||||
|
:draw(function(def, parent)
|
||||||
|
local scroll = parent.add{
|
||||||
|
type = "scroll-pane",
|
||||||
|
direction = "vertical",
|
||||||
|
horizontal_scroll_policy = "never",
|
||||||
|
vertical_scroll_policy = "auto",
|
||||||
|
style = "scroll_pane_under_subheader",
|
||||||
|
}
|
||||||
|
scroll.style.horizontally_stretchable = true
|
||||||
|
scroll.style.maximal_height = 224
|
||||||
|
scroll.style.padding = 0
|
||||||
|
|
||||||
|
-- This is required because vertical_spacing can't be set on a scroll pane
|
||||||
|
return scroll.add{
|
||||||
|
type = "flow",
|
||||||
|
direction = "vertical",
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
:style{
|
||||||
|
horizontally_stretchable = true,
|
||||||
|
vertical_spacing = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- The main container for the toolbar settings
|
||||||
|
elements.toolbar_settings = ExpGui.element("toolbar_settings")
|
||||||
|
:draw(function(def, parent)
|
||||||
|
-- Draw the container
|
||||||
|
local frame = ExpGui.elements.container(parent, 268)
|
||||||
|
frame.style.maximal_width = 268
|
||||||
|
frame.style.minimal_width = 268
|
||||||
|
|
||||||
|
-- Draw the header
|
||||||
|
local player = ExpGui.get_player(parent)
|
||||||
|
local header = ExpGui.elements.header(frame, {
|
||||||
|
caption = { "exp-gui_toolbar-settings.main-caption" },
|
||||||
|
tooltip = { "exp-gui_toolbar-settings.main-tooltip" },
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Draw the toolbar control buttons
|
||||||
|
local toggle_element = elements.toggle_toolbar(header)
|
||||||
|
toggle_element.toggled = Toolbar.get_visible_state(player)
|
||||||
|
elements.reset_toolbar(header)
|
||||||
|
|
||||||
|
def.data[player] = elements.toolbar_list(frame)
|
||||||
|
Toolbar._ensure_elements(player)
|
||||||
|
return frame.parent
|
||||||
|
end)
|
||||||
|
|
||||||
|
ExpGui.add_left_element(elements.core_button_flow, true)
|
||||||
|
ExpGui.add_left_element(elements.toolbar_settings, false)
|
||||||
|
ExpGui.add_top_element(elements.close_toolbar, true)
|
||||||
|
|
||||||
|
return Toolbar
|
||||||
@@ -41,6 +41,7 @@ return {
|
|||||||
-- 'modules.data.bonus',
|
-- 'modules.data.bonus',
|
||||||
"modules.data.personal-logistic",
|
"modules.data.personal-logistic",
|
||||||
"modules.data.language",
|
"modules.data.language",
|
||||||
|
--"modules.data.toolbar",
|
||||||
|
|
||||||
--- GUI
|
--- GUI
|
||||||
"modules.gui.readme",
|
"modules.gui.readme",
|
||||||
@@ -60,7 +61,6 @@ return {
|
|||||||
"modules.gui.production",
|
"modules.gui.production",
|
||||||
"modules.gui.playerdata",
|
"modules.gui.playerdata",
|
||||||
"modules.gui.surveillance",
|
"modules.gui.surveillance",
|
||||||
--"modules.gui.toolbar", -- must be loaded last to register toolbar handlers
|
|
||||||
|
|
||||||
"modules.graftorio.require", -- graftorio
|
"modules.graftorio.require", -- graftorio
|
||||||
--- Config Files
|
--- Config Files
|
||||||
|
|||||||
@@ -320,14 +320,6 @@ type-player=Player
|
|||||||
type-static=Static
|
type-static=Static
|
||||||
type-player-loop=Player loop
|
type-player-loop=Player loop
|
||||||
|
|
||||||
[toolbar]
|
|
||||||
main-caption=Toolbox
|
|
||||||
main-tooltip=Toolbox Settings\nUse the checkboxs to select facourites
|
|
||||||
reset=Reset All
|
|
||||||
toggle=Toggle Favourites
|
|
||||||
move-up=Move Up
|
|
||||||
move-down=Move Down
|
|
||||||
|
|
||||||
[research]
|
[research]
|
||||||
msg=[color=255, 255, 255] Research completed at __1__ - [technology=__2__][/color]
|
msg=[color=255, 255, 255] Research completed at __1__ - [technology=__2__][/color]
|
||||||
inf=[color=255, 255, 255] Research completed at __1__ - [technology=__2__] - __3__[/color]
|
inf=[color=255, 255, 255] Research completed at __1__ - [technology=__2__] - __3__[/color]
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ end
|
|||||||
local HasEnabledDecon = PlayerData.Settings:combine("HasEnabledDecon")
|
local HasEnabledDecon = PlayerData.Settings:combine("HasEnabledDecon")
|
||||||
HasEnabledDecon:set_default(false)
|
HasEnabledDecon:set_default(false)
|
||||||
|
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "toggle-tree-decon",
|
name = "toggle-tree-decon",
|
||||||
sprite = "entity/tree-01",
|
sprite = "entity/tree-01",
|
||||||
tooltip = { "tree-decon.main-tooltip" },
|
tooltip = { "tree-decon.main-tooltip" },
|
||||||
@@ -43,11 +43,11 @@ Gui.create_toolbar_button{
|
|||||||
visible = function(player, _)
|
visible = function(player, _)
|
||||||
return Roles.player_allowed(player, "fast-tree-decon")
|
return Roles.player_allowed(player, "fast-tree-decon")
|
||||||
end
|
end
|
||||||
}:on_event(Gui.on_toolbar_button_toggled, function(def, event)
|
}:on_click(function(def, event, element)
|
||||||
--- @cast event EventData.on_toolbar_button_toggled
|
|
||||||
local player = Gui.get_player(event)
|
local player = Gui.get_player(event)
|
||||||
HasEnabledDecon:set(player, event.state)
|
local state = Gui.toolbar.get_button_toggled_state(def, player)
|
||||||
player.print{ "tree-decon.toggle-msg", event.state and { "tree-decon.enabled" } or { "tree-decon.disabled" } }
|
HasEnabledDecon:set(player, state)
|
||||||
|
player.print{ "tree-decon.toggle-msg", state and { "tree-decon.enabled" } or { "tree-decon.disabled" } }
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Add trees to queue when marked, only allows simple entities and for players with role permission
|
-- Add trees to queue when marked, only allows simple entities and for players with role permission
|
||||||
|
|||||||
190
exp_legacy/module/modules/data/toolbar.lua
Normal file
190
exp_legacy/module/modules/data/toolbar.lua
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
local Gui = require("modules/exp_gui")
|
||||||
|
local ExpElement = require("modules/exp_gui/prototype")
|
||||||
|
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
||||||
|
|
||||||
|
-- Used to store the state of the toolbar when a player leaves
|
||||||
|
local ToolbarState = PlayerData.Settings:combine("ToolbarState")
|
||||||
|
ToolbarState:set_metadata{
|
||||||
|
stringify = function(value)
|
||||||
|
local buttons, favourites = 0, 0
|
||||||
|
for _, state in ipairs(value) do
|
||||||
|
buttons = buttons + 1
|
||||||
|
if state.favourite then
|
||||||
|
favourites = favourites + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return string.format("Buttons: %d, Favourites: %d", buttons, favourites)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Set the default value for the datastore
|
||||||
|
local datastore_id_map = {} --- @type table<string, ExpElement>
|
||||||
|
local toolbar_default_state = {}
|
||||||
|
ToolbarState:set_default(toolbar_default_state)
|
||||||
|
|
||||||
|
--- Get the datastore id for this element define, to best of ability it should be unique between versions
|
||||||
|
local function to_datastore_id(element_define)
|
||||||
|
-- First try to use the tooltip locale string
|
||||||
|
local tooltip = element_define.tooltip
|
||||||
|
if type(tooltip) == "table" then
|
||||||
|
return tooltip[1]:gsub("%.(.+)", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Then try to use the caption or sprite
|
||||||
|
return element_define.caption or element_define.sprite
|
||||||
|
end
|
||||||
|
|
||||||
|
--- For all top element, register an on click which will copy their style
|
||||||
|
for index, element_define in ipairs(Gui.top_elements) do
|
||||||
|
-- Insert the element into the id map
|
||||||
|
datastore_id_map[to_datastore_id(element_define)] = element_define -- Backwards Compatibility
|
||||||
|
datastore_id_map[element_define.name] = element_define
|
||||||
|
|
||||||
|
-- Add the element to the default state
|
||||||
|
table.insert(toolbar_default_state, {
|
||||||
|
element = element_define.uid,
|
||||||
|
favourite = true,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the top order based on the players settings
|
||||||
|
Gui.inject_top_flow_order(function(player)
|
||||||
|
local order = ToolbarState:get(player)
|
||||||
|
|
||||||
|
local elements = {}
|
||||||
|
for index, state in ipairs(order) do
|
||||||
|
elements[index] = Gui.defines[state.element]
|
||||||
|
end
|
||||||
|
|
||||||
|
return elements
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Get the left order based on the player settings, with toolbar menu first, and all remaining after
|
||||||
|
Gui.inject_left_flow_order(function(player)
|
||||||
|
local order = Gui.get_top_flow_order(player)
|
||||||
|
local elements, element_map = { toolbar_container }, { [toolbar_container] = true }
|
||||||
|
|
||||||
|
-- Add the flows that have a top element
|
||||||
|
for _, element_define in ipairs(order) do
|
||||||
|
if element_define.left_flow_element then
|
||||||
|
table.insert(elements, element_define.left_flow_element)
|
||||||
|
element_map[element_define.left_flow_element] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add the flows that dont have a top element
|
||||||
|
for _, element_define in ipairs(Gui.left_elements) do
|
||||||
|
if not element_map[element_define] then
|
||||||
|
table.insert(elements, element_define)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return elements
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Overwrite the default update top flow
|
||||||
|
local _update_top_flow = Gui.update_top_flow
|
||||||
|
function Gui.update_top_flow(player)
|
||||||
|
_update_top_flow(player) -- Call the original
|
||||||
|
|
||||||
|
local order = ToolbarState:get(player)
|
||||||
|
for index, state in ipairs(order) do
|
||||||
|
local element_define = Gui.defines[state.element]
|
||||||
|
local top_element = Gui.get_top_element(player, element_define)
|
||||||
|
top_element.visible = top_element.visible and state.favourite or false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Uncompress the data to be more useable
|
||||||
|
ToolbarState:on_load(function(player_name, value)
|
||||||
|
-- If there is no value, do nothing
|
||||||
|
if value == nil then return end
|
||||||
|
--- @cast value [ string[], string[], string[], boolean ]
|
||||||
|
|
||||||
|
-- Create a hash map of the favourites
|
||||||
|
local favourites = {}
|
||||||
|
for _, id in ipairs(value[2]) do
|
||||||
|
favourites[id] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Read the order from the value
|
||||||
|
local elements = {}
|
||||||
|
local element_hash = {}
|
||||||
|
for index, id in ipairs(value[1]) do
|
||||||
|
local element = datastore_id_map[id]
|
||||||
|
if element and not element_hash[element.name] then
|
||||||
|
element_hash[element.name] = true
|
||||||
|
elements[index] = {
|
||||||
|
element = element,
|
||||||
|
favourite = favourites[id] or false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add any in the default state that are missing
|
||||||
|
for _, state in ipairs(toolbar_default_state) do
|
||||||
|
if not element_hash[state.element] then
|
||||||
|
table.insert(elements, table.deep_copy(state))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create a hash map of the open left flows
|
||||||
|
local open_left_elements = {}
|
||||||
|
for _, id in ipairs(value[3]) do
|
||||||
|
local element = datastore_id_map[id]
|
||||||
|
local left_element = element.left_flow_element
|
||||||
|
if left_element then
|
||||||
|
open_left_elements[left_element] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the visible state of all left flows
|
||||||
|
local player = assert(game.get_player(player_name))
|
||||||
|
for left_element in pairs(Gui.left_elements) do
|
||||||
|
Gui.set_left_element_visible(left_element, player, open_left_elements[left_element] or false)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the toolbar visible state
|
||||||
|
Gui.set_top_flow_visible(player, value[4])
|
||||||
|
|
||||||
|
-- Set the data now and update now, ideally this would be on_update but that had too large of a latency
|
||||||
|
ToolbarState:raw_set(player_name, elements)
|
||||||
|
Gui.reorder_top_flow(player)
|
||||||
|
Gui.reorder_left_flow(player)
|
||||||
|
reorder_toolbar_menu(player)
|
||||||
|
|
||||||
|
return elements
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Save the current state of the players toolbar menu
|
||||||
|
ToolbarState:on_save(function(player_name, value)
|
||||||
|
if value == nil then return nil end -- Don't save default
|
||||||
|
local order, favourites, left_flows = {}, {}, {}
|
||||||
|
|
||||||
|
local player = assert(game.get_player(player_name))
|
||||||
|
local top_flow_open = Gui.get_top_flow(player).parent.visible
|
||||||
|
|
||||||
|
for index, state in ipairs(value) do
|
||||||
|
-- Add the element to the order array
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
local element_define = ExpElement._elements[state.element]
|
||||||
|
local id = to_datastore_id(element_define)
|
||||||
|
order[index] = id
|
||||||
|
|
||||||
|
-- If its a favourite then insert it
|
||||||
|
if state.favourite then
|
||||||
|
table.insert(favourites, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If it has a left flow and its open then insert it
|
||||||
|
if element_define.left_flow_element then
|
||||||
|
local left_element = Gui.get_left_element(element_define.left_flow_element, player)
|
||||||
|
if left_element.visible then
|
||||||
|
table.insert(left_flows, id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return { order, favourites, left_flows, top_flow_open }
|
||||||
|
end)
|
||||||
@@ -296,7 +296,7 @@ autofill_container = Gui.element("autofill_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(autofill_container, false)
|
Gui.add_left_element(autofill_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "autofill_toggle",
|
name = "autofill_toggle",
|
||||||
left_element = autofill_container,
|
left_element = autofill_container,
|
||||||
sprite = config.icon,
|
sprite = config.icon,
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ bonus_container = Gui.element("bonus_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(bonus_container, false)
|
Gui.add_left_element(bonus_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "bonus_toggle",
|
name = "bonus_toggle",
|
||||||
left_element = bonus_container,
|
left_element = bonus_container,
|
||||||
sprite = "item/exoskeleton-equipment",
|
sprite = "item/exoskeleton-equipment",
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
local ExpElement = require("modules/exp_gui/prototype")
|
local ExpElement = require("modules/exp_gui/prototype")
|
||||||
|
local ExpData = require("modules/exp_gui/data")
|
||||||
|
local ExpIter = require("modules/exp_gui/iter")
|
||||||
local Color = require("modules/exp_util/include/color")
|
local Color = require("modules/exp_util/include/color")
|
||||||
|
|
||||||
local Gui = require("modules.exp_legacy.utils.gui") --- @dep utils.gui
|
local Gui = require("modules.exp_legacy.utils.gui") --- @dep utils.gui
|
||||||
@@ -87,11 +89,23 @@ Gui.on_click(
|
|||||||
element.style.font_color = Color.orange
|
element.style.font_color = Color.orange
|
||||||
data.selected_header = element
|
data.selected_header = element
|
||||||
|
|
||||||
input_text_box.text = concat{ "ExpElement._elements[", element_name, "]" }
|
input_text_box.text = concat{ "ExpElement._elements[\"", element_name, "\"]" }
|
||||||
input_text_box.style.font_color = Color.black
|
input_text_box.style.font_color = Color.black
|
||||||
|
|
||||||
--- @diagnostic disable-next-line invisible
|
--- @diagnostic disable-next-line invisible
|
||||||
local content = dump(ExpElement._elements[element_name]) or "nil"
|
local define = ExpElement._elements[element_name]
|
||||||
|
local content = dump({
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
debug = define._debug,
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
has_handlers = define._has_handlers,
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
track_elements = define._track_elements,
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
elements = ExpIter._scopes[element_name],
|
||||||
|
--- @diagnostic disable-next-line invisible
|
||||||
|
data = ExpData._scopes[element_name]._raw,
|
||||||
|
}) or "nil"
|
||||||
right_panel.text = content
|
right_panel.text = content
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ local function landfill_gui_add_landfill(blueprint)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Add the toolbar button
|
--- Add the toolbar button
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "landfill",
|
name = "landfill",
|
||||||
sprite = "item/landfill",
|
sprite = "item/landfill",
|
||||||
tooltip = { "landfill.main-tooltip" },
|
tooltip = { "landfill.main-tooltip" },
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ module_container = Gui.element("module_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(module_container, false)
|
Gui.add_left_element(module_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "module_toggle",
|
name = "module_toggle",
|
||||||
left_element = module_container,
|
left_element = module_container,
|
||||||
sprite = "item/productivity-module-3",
|
sprite = "item/productivity-module-3",
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ local player_list_container = Gui.element("player_list_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(player_list_container, true)
|
Gui.add_left_element(player_list_container, true)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "player_list_toggle",
|
name = "player_list_toggle",
|
||||||
left_element = player_list_container,
|
left_element = player_list_container,
|
||||||
sprite = "entity/character",
|
sprite = "entity/character",
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ pd_container = Gui.element("pd_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(pd_container, false)
|
Gui.add_left_element(pd_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "player_data_toggle",
|
name = "player_data_toggle",
|
||||||
left_element = pd_container,
|
left_element = pd_container,
|
||||||
sprite = "item/power-armor-mk2",
|
sprite = "item/power-armor-mk2",
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ production_container = Gui.element("production_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(production_container, false)
|
Gui.add_left_element(production_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "production_toggle",
|
name = "production_toggle",
|
||||||
left_element = production_container,
|
left_element = production_container,
|
||||||
sprite = "entity/assembling-machine-3",
|
sprite = "entity/assembling-machine-3",
|
||||||
|
|||||||
@@ -438,19 +438,17 @@ local readme = Gui.element("readme")
|
|||||||
end)
|
end)
|
||||||
:on_opened(function(def, event)
|
:on_opened(function(def, event)
|
||||||
local player = Gui.get_player(event)
|
local player = Gui.get_player(event)
|
||||||
local button = Gui.get_top_element(readme_toggle, player)
|
Gui.toolbar.set_button_toggled_state(readme_toggle, player, true)
|
||||||
Gui.set_toolbar_button_style(button, true)
|
|
||||||
end)
|
end)
|
||||||
:on_closed(function(def, event, element)
|
:on_closed(function(def, event, element)
|
||||||
local player = Gui.get_player(event)
|
local player = Gui.get_player(event)
|
||||||
local button = Gui.get_top_element(readme_toggle, player)
|
Gui.toolbar.set_button_toggled_state(readme_toggle, player, false)
|
||||||
Gui.set_toolbar_button_style(button, false)
|
|
||||||
Gui.destroy_if_valid(element)
|
Gui.destroy_if_valid(element)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--- Toggle button for the readme gui
|
--- Toggle button for the readme gui
|
||||||
readme_toggle =
|
readme_toggle =
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "readme_toggle",
|
name = "readme_toggle",
|
||||||
auto_toggle = true,
|
auto_toggle = true,
|
||||||
sprite = "virtual-signal/signal-info",
|
sprite = "virtual-signal/signal-info",
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ local research_container = Gui.element("research_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(research_container, false)
|
Gui.add_left_element(research_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "research_toggle",
|
name = "research_toggle",
|
||||||
left_element = research_container,
|
left_element = research_container,
|
||||||
sprite = "item/space-science-pack",
|
sprite = "item/space-science-pack",
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ local rocket_list_container = Gui.element("rocket_list_container")
|
|||||||
Gui.add_left_element(rocket_list_container, function(player, element)
|
Gui.add_left_element(rocket_list_container, function(player, element)
|
||||||
return player.force.rockets_launched > 0 and Roles.player_allowed(player, "gui/rocket-info")
|
return player.force.rockets_launched > 0 and Roles.player_allowed(player, "gui/rocket-info")
|
||||||
end)
|
end)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "rocket_list_toggle",
|
name = "rocket_list_toggle",
|
||||||
left_element = rocket_list_container,
|
left_element = rocket_list_container,
|
||||||
sprite = "item/rocket-silo",
|
sprite = "item/rocket-silo",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ local science_info = Gui.element("science_info")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(science_info, false)
|
Gui.add_left_element(science_info, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "science_info_toggle",
|
name = "science_info_toggle",
|
||||||
left_element = science_info,
|
left_element = science_info,
|
||||||
sprite = "entity/lab",
|
sprite = "entity/lab",
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ local cctv_container = Gui.element("cctv_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(cctv_container, false)
|
Gui.add_left_element(cctv_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "cctv_toggle",
|
name = "cctv_toggle",
|
||||||
left_element = cctv_container,
|
left_element = cctv_container,
|
||||||
sprite = "entity/radar",
|
sprite = "entity/radar",
|
||||||
|
|||||||
@@ -557,7 +557,7 @@ Gui.add_left_element(task_list_container, function(player)
|
|||||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||||
return #task_ids > 0
|
return #task_ids > 0
|
||||||
end)
|
end)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "task_list_toggle",
|
name = "task_list_toggle",
|
||||||
left_element = task_list_container,
|
left_element = task_list_container,
|
||||||
sprite = "utility/not_enough_repair_packs_icon",
|
sprite = "utility/not_enough_repair_packs_icon",
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ tool_container = Gui.element("tool_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(tool_container, false)
|
Gui.add_left_element(tool_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "tool_toggle",
|
name = "tool_toggle",
|
||||||
left_element = tool_container,
|
left_element = tool_container,
|
||||||
sprite = "item/repair-pack",
|
sprite = "item/repair-pack",
|
||||||
|
|||||||
@@ -1,528 +0,0 @@
|
|||||||
local Gui = require("modules.exp_legacy.expcore.gui") --- @dep expcore.gui
|
|
||||||
local PlayerData = require("modules.exp_legacy.expcore.player_data") --- @dep expcore.player_data
|
|
||||||
|
|
||||||
-- Used to store the state of the toolbar when a player leaves
|
|
||||||
local ToolbarState = PlayerData.Settings:combine("ToolbarState")
|
|
||||||
ToolbarState:set_metadata{
|
|
||||||
stringify = function(value)
|
|
||||||
local buttons, favourites = 0, 0
|
|
||||||
for _, state in ipairs(value) do
|
|
||||||
buttons = buttons + 1
|
|
||||||
if state.favourite then
|
|
||||||
favourites = favourites + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return string.format("Buttons: %d, Favourites: %d", buttons, favourites)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Styles used for sprite buttons
|
|
||||||
local button_size = 20
|
|
||||||
local Styles = {
|
|
||||||
header = Gui.sprite_style(22),
|
|
||||||
item = Gui.sprite_style(button_size),
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Set the style of the fake toolbar element
|
|
||||||
local function copy_style(src, dst)
|
|
||||||
dst.style = src.style.name
|
|
||||||
dst.style.height = button_size
|
|
||||||
dst.style.width = button_size
|
|
||||||
dst.style.padding = -2
|
|
||||||
end
|
|
||||||
|
|
||||||
local toolbar_container, move_up, move_down, toggle_toolbar
|
|
||||||
|
|
||||||
--- Reorder the buttons relative to each other, this will update the datastore
|
|
||||||
local function move_toolbar_button(player, item, offset)
|
|
||||||
local old_index = item.get_index_in_parent()
|
|
||||||
local new_index = old_index + offset
|
|
||||||
|
|
||||||
-- Ideally the following would all happen in on_update but this had too much latency
|
|
||||||
-- Swap the position in the list
|
|
||||||
local list = item.parent
|
|
||||||
local other_item = list.children[new_index]
|
|
||||||
list.swap_children(old_index, new_index)
|
|
||||||
|
|
||||||
-- Swap the position in the top flow, offset by 1 because of settings button
|
|
||||||
local top_flow = Gui.get_top_flow(player)
|
|
||||||
top_flow.swap_children(old_index + 1, new_index + 1)
|
|
||||||
|
|
||||||
-- Check if the element has a left element to move
|
|
||||||
local element_define = Gui.defines[item.tags.top_element_uid]
|
|
||||||
local other_define = Gui.defines[other_item.tags.top_element_uid]
|
|
||||||
if element_define.left_flow_element and other_define.left_flow_element then
|
|
||||||
local left_element = Gui.get_left_element(player, element_define.left_flow_element)
|
|
||||||
local other_left_element = Gui.get_left_element(player, other_define.left_flow_element)
|
|
||||||
local left_index = left_element.get_index_in_parent()
|
|
||||||
local other_index = other_left_element.get_index_in_parent()
|
|
||||||
left_element.parent.swap_children(left_index, other_index)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If we are moving in/out of first/last place we need to update the move buttons
|
|
||||||
local last_index = #list.children
|
|
||||||
if old_index == 1 then -- Moving out of index 1
|
|
||||||
other_item.move[move_up.name].enabled = false
|
|
||||||
item.move[move_up.name].enabled = true
|
|
||||||
elseif new_index == 1 then -- Moving into index 1
|
|
||||||
other_item.move[move_up.name].enabled = true
|
|
||||||
item.move[move_up.name].enabled = false
|
|
||||||
elseif old_index == last_index then -- Moving out of the last index
|
|
||||||
other_item.move[move_down.name].enabled = false
|
|
||||||
item.move[move_down.name].enabled = true
|
|
||||||
elseif new_index == last_index then -- Moving into the last index
|
|
||||||
other_item.move[move_down.name].enabled = true
|
|
||||||
item.move[move_down.name].enabled = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update the datastore state
|
|
||||||
ToolbarState:update(player, function(_, order)
|
|
||||||
local tmp = order[old_index]
|
|
||||||
order[old_index] = order[new_index]
|
|
||||||
order[new_index] = tmp
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Reorder the toolbar buttons
|
|
||||||
local function reorder_toolbar_menu(player)
|
|
||||||
local frame = Gui.get_left_element(player, toolbar_container)
|
|
||||||
local list = frame.container.scroll.list
|
|
||||||
local order = ToolbarState:get(player)
|
|
||||||
local last_index = #order
|
|
||||||
|
|
||||||
-- Reorder the buttons
|
|
||||||
for index, state in ipairs(order) do
|
|
||||||
local element_define = Gui.defines[state.element_uid]
|
|
||||||
|
|
||||||
-- Switch item order
|
|
||||||
local item = list[element_define.name]
|
|
||||||
list.swap_children(index, item.get_index_in_parent())
|
|
||||||
|
|
||||||
-- Check if the player is allowed to see the button
|
|
||||||
local allowed = element_define.authenticator
|
|
||||||
if type(allowed) == "function" then allowed = allowed(player) end
|
|
||||||
|
|
||||||
-- Update the checkbox state and item visibility
|
|
||||||
local toolbar_button = Gui.get_top_element(player, element_define)
|
|
||||||
toolbar_button.visible = allowed and state.favourite or false
|
|
||||||
item.checkbox.state = state.favourite
|
|
||||||
|
|
||||||
-- Update the state if the move buttons
|
|
||||||
item.move[move_up.name].enabled = index ~= 1
|
|
||||||
item.move[move_down.name].enabled = index ~= last_index
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update the state of the toggle button
|
|
||||||
local button = frame.container.header.alignment[toggle_toolbar.name]
|
|
||||||
button.enabled = Gui.top_flow_has_visible_elements(player)
|
|
||||||
button.toggled = Gui.get_top_flow(player).parent.visible
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Resets the toolbar to its default state when pressed
|
|
||||||
-- @element reset_toolbar
|
|
||||||
local reset_toolbar =
|
|
||||||
Gui.element{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/reset",
|
|
||||||
style = "shortcut_bar_button_red",
|
|
||||||
tooltip = { "toolbar.reset" },
|
|
||||||
name = Gui.unique_static_name,
|
|
||||||
}
|
|
||||||
:style(Gui.sprite_style(Styles.header.width, -1))
|
|
||||||
:on_click(function(player)
|
|
||||||
ToolbarState:set(player, nil)
|
|
||||||
Gui.toggle_top_flow(player, true)
|
|
||||||
reorder_toolbar_menu(player)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Replaces the default method for opening and closing the toolbar
|
|
||||||
-- @element toggle_toolbar
|
|
||||||
toggle_toolbar =
|
|
||||||
Gui.element{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/bookmark",
|
|
||||||
tooltip = { "toolbar.toggle" },
|
|
||||||
style = "tool_button",
|
|
||||||
auto_toggle = true,
|
|
||||||
name = Gui.unique_static_name,
|
|
||||||
}
|
|
||||||
:style(Styles.header)
|
|
||||||
:on_click(function(player, element)
|
|
||||||
Gui.toggle_top_flow(player, element.toggled)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Move an element up the list
|
|
||||||
-- @element move_up
|
|
||||||
move_up =
|
|
||||||
Gui.element{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/speed_up",
|
|
||||||
tooltip = { "toolbar.move-up" },
|
|
||||||
name = Gui.unique_static_name,
|
|
||||||
}
|
|
||||||
:style(Styles.item)
|
|
||||||
:on_click(function(player, element)
|
|
||||||
local item = element.parent.parent
|
|
||||||
move_toolbar_button(player, item, -1)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Move an element down the list
|
|
||||||
-- @element move_down
|
|
||||||
move_down =
|
|
||||||
Gui.element{
|
|
||||||
type = "sprite-button",
|
|
||||||
sprite = "utility/speed_down",
|
|
||||||
tooltip = { "toolbar.move-down" },
|
|
||||||
name = Gui.unique_static_name,
|
|
||||||
}
|
|
||||||
:style(Styles.item)
|
|
||||||
:on_click(function(player, element)
|
|
||||||
local item = element.parent.parent
|
|
||||||
move_toolbar_button(player, item, 1)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- A flow which represents one item in the toolbar list
|
|
||||||
-- @element toolbar_list_item
|
|
||||||
local toolbar_list_item =
|
|
||||||
Gui.element(function(definition, parent, element_define)
|
|
||||||
local flow = parent.add{
|
|
||||||
type = "frame",
|
|
||||||
style = "shortcut_selection_row",
|
|
||||||
name = element_define.name,
|
|
||||||
tags = {
|
|
||||||
top_element_uid = element_define.uid,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
flow.style.horizontally_stretchable = true
|
|
||||||
flow.style.vertical_align = "center"
|
|
||||||
|
|
||||||
-- Add the button and the icon edit button
|
|
||||||
local element = element_define(flow)
|
|
||||||
local player = Gui.get_player_from_element(parent)
|
|
||||||
local top_element = Gui.get_top_element(player, element_define)
|
|
||||||
copy_style(top_element, element)
|
|
||||||
|
|
||||||
-- Add the checkbox that can toggle the visibility
|
|
||||||
local checkbox = flow.add{
|
|
||||||
type = "checkbox",
|
|
||||||
name = "checkbox",
|
|
||||||
caption = element_define.tooltip or element_define.caption or "None",
|
|
||||||
state = top_element.visible or false,
|
|
||||||
tags = {
|
|
||||||
top_element_name = element_define.name,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
definition:triggers_events(checkbox)
|
|
||||||
checkbox.style.width = 180
|
|
||||||
|
|
||||||
-- Add the buttons used to move the flow up and down
|
|
||||||
local move_flow = flow.add{ type = "flow", name = "move" }
|
|
||||||
move_flow.style.horizontal_spacing = 0
|
|
||||||
move_up(move_flow)
|
|
||||||
move_down(move_flow)
|
|
||||||
|
|
||||||
return definition:no_events(flow)
|
|
||||||
end)
|
|
||||||
:on_checked_changed(function(player, element)
|
|
||||||
local top_flow = Gui.get_top_flow(player)
|
|
||||||
local top_element = top_flow[element.tags.top_element_name]
|
|
||||||
local had_visible = Gui.top_flow_has_visible_elements(player)
|
|
||||||
top_element.visible = element.state
|
|
||||||
|
|
||||||
-- Check if we are on the edge case between 0 and 1 visible elements
|
|
||||||
if element.state and not had_visible then
|
|
||||||
Gui.toggle_top_flow(player, true)
|
|
||||||
local container = element.parent.parent.parent.parent
|
|
||||||
local button = container.header.alignment[toggle_toolbar.name]
|
|
||||||
button.toggled = true
|
|
||||||
button.enabled = true
|
|
||||||
elseif not element.state and not Gui.top_flow_has_visible_elements(player) then
|
|
||||||
Gui.toggle_top_flow(player, false)
|
|
||||||
local container = element.parent.parent.parent.parent
|
|
||||||
local button = container.header.alignment[toggle_toolbar.name]
|
|
||||||
button.toggled = false
|
|
||||||
button.enabled = false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update the datastore state
|
|
||||||
ToolbarState:update(player, function(_, order)
|
|
||||||
local index = element.parent.get_index_in_parent()
|
|
||||||
order[index].favourite = element.state
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Scrollable list of all toolbar buttons
|
|
||||||
-- @element toolbar_list
|
|
||||||
local toolbar_list =
|
|
||||||
Gui.element(function(_, parent)
|
|
||||||
-- This is a scroll pane for the list
|
|
||||||
local scroll_pane = parent.add{
|
|
||||||
name = "scroll",
|
|
||||||
type = "scroll-pane",
|
|
||||||
direction = "vertical",
|
|
||||||
horizontal_scroll_policy = "never",
|
|
||||||
vertical_scroll_policy = "auto",
|
|
||||||
style = "scroll_pane_under_subheader",
|
|
||||||
}
|
|
||||||
scroll_pane.style.horizontally_stretchable = true
|
|
||||||
scroll_pane.style.padding = 0
|
|
||||||
scroll_pane.style.maximal_height = 224
|
|
||||||
|
|
||||||
-- This flow is the list, we need a linear list because of get_index_in_parent
|
|
||||||
local flow = scroll_pane.add{
|
|
||||||
name = "list",
|
|
||||||
type = "flow",
|
|
||||||
direction = "vertical",
|
|
||||||
}
|
|
||||||
flow.style.vertical_spacing = 0
|
|
||||||
flow.style.horizontally_stretchable = true
|
|
||||||
|
|
||||||
return flow
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Main toolbar container for the left flow
|
|
||||||
-- @element toolbar_container
|
|
||||||
toolbar_container =
|
|
||||||
Gui.element(function(definition, parent)
|
|
||||||
-- Draw the internal container
|
|
||||||
local container = Gui.container(parent, definition.name, 268)
|
|
||||||
container.style.maximal_width = 268
|
|
||||||
container.style.minimal_width = 268
|
|
||||||
|
|
||||||
-- Draw the header
|
|
||||||
local player = Gui.get_player_from_element(parent)
|
|
||||||
local header = Gui.header(container, { "toolbar.main-caption" }, { "toolbar.main-tooltip" }, true)
|
|
||||||
|
|
||||||
-- Draw the toolbar control buttons
|
|
||||||
local toggle_element = toggle_toolbar(header)
|
|
||||||
toggle_element.toggled = Gui.get_top_flow(player).visible
|
|
||||||
reset_toolbar(header)
|
|
||||||
|
|
||||||
-- Draw toolbar list element
|
|
||||||
local list_element = toolbar_list(container)
|
|
||||||
local flow_order = Gui.get_top_flow_order(player)
|
|
||||||
|
|
||||||
for _, element_define in ipairs(flow_order) do
|
|
||||||
-- Ensure the element exists
|
|
||||||
local element = list_element[element_define.name]
|
|
||||||
if not element then
|
|
||||||
element = toolbar_list_item(list_element, element_define)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the visible state
|
|
||||||
local allowed = element_define.authenticator
|
|
||||||
if type(allowed) == "function" then allowed = allowed(player) end
|
|
||||||
element.visible = allowed or false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the state of the move buttons for the first and last element
|
|
||||||
local children = list_element.children
|
|
||||||
children[1].move[move_up.name].enabled = false
|
|
||||||
children[#children].move[move_down.name].enabled = false
|
|
||||||
|
|
||||||
-- Return the external container
|
|
||||||
return container.parent
|
|
||||||
end)
|
|
||||||
:static_name(Gui.unique_static_name)
|
|
||||||
:add_to_left_flow(false)
|
|
||||||
|
|
||||||
--- Set the default value for the datastore
|
|
||||||
local datastore_id_map = {}
|
|
||||||
local toolbar_default_state = {}
|
|
||||||
ToolbarState:set_default(toolbar_default_state)
|
|
||||||
|
|
||||||
--- Get the datastore id for this element define, to best of ability it should be unique between versions
|
|
||||||
local function to_datastore_id(element_define)
|
|
||||||
-- First try to use the tooltip locale string
|
|
||||||
local tooltip = element_define.tooltip
|
|
||||||
if type(tooltip) == "table" then
|
|
||||||
return tooltip[1]:gsub("%.(.+)", "")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Then try to use the caption or sprite
|
|
||||||
return element_define.caption or element_define.sprite
|
|
||||||
end
|
|
||||||
|
|
||||||
--- For all top element, register an on click which will copy their style
|
|
||||||
for index, element_define in ipairs(Gui.top_elements) do
|
|
||||||
-- This is a bit hacky, the gui system cant have multiple handlers registered
|
|
||||||
local prev_handler = element_define[Gui.events.on_toolbar_button_toggled]
|
|
||||||
|
|
||||||
-- Add the handler for when the button is toggled
|
|
||||||
element_define:on_event(Gui.events.on_toolbar_button_toggled, function(player, element, event)
|
|
||||||
if prev_handler then prev_handler(player, element, event) end -- Kind of hacky but works
|
|
||||||
local frame = Gui.get_left_element(player, toolbar_container)
|
|
||||||
if not frame then return end -- Gui might not be loaded yet
|
|
||||||
if not frame.container then
|
|
||||||
log(frame.name)
|
|
||||||
log(frame.parent.name)
|
|
||||||
end
|
|
||||||
local button = frame.container.scroll.list[element_define.name][element_define.name]
|
|
||||||
local toolbar_button = Gui.get_top_element(player, element_define)
|
|
||||||
copy_style(toolbar_button, button)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Insert the element into the id map
|
|
||||||
local id = to_datastore_id(element_define)
|
|
||||||
if datastore_id_map[id] then
|
|
||||||
error(string.format("All toolbar elements need a unique id to be saved correctly, %d (%s) and %d (%s) share the id %s",
|
|
||||||
datastore_id_map[id].uid, datastore_id_map[id].defined_at, element_define.uid, element_define.defined_at, id
|
|
||||||
))
|
|
||||||
end
|
|
||||||
datastore_id_map[id] = element_define
|
|
||||||
|
|
||||||
-- Add the element to the default state
|
|
||||||
table.insert(toolbar_default_state, {
|
|
||||||
element_uid = element_define.uid,
|
|
||||||
favourite = true,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the top order based on the players settings
|
|
||||||
Gui.inject_top_flow_order(function(player)
|
|
||||||
local order = ToolbarState:get(player)
|
|
||||||
|
|
||||||
local elements = {}
|
|
||||||
for index, state in ipairs(order) do
|
|
||||||
elements[index] = Gui.defines[state.element_uid]
|
|
||||||
end
|
|
||||||
|
|
||||||
return elements
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Get the left order based on the player settings, with toolbar menu first, and all remaining after
|
|
||||||
Gui.inject_left_flow_order(function(player)
|
|
||||||
local order = Gui.get_top_flow_order(player)
|
|
||||||
local elements, element_map = { toolbar_container }, { [toolbar_container] = true }
|
|
||||||
|
|
||||||
-- Add the flows that have a top element
|
|
||||||
for _, element_define in ipairs(order) do
|
|
||||||
if element_define.left_flow_element then
|
|
||||||
table.insert(elements, element_define.left_flow_element)
|
|
||||||
element_map[element_define.left_flow_element] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add the flows that dont have a top element
|
|
||||||
for _, element_define in ipairs(Gui.left_elements) do
|
|
||||||
if not element_map[element_define] then
|
|
||||||
table.insert(elements, element_define)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return elements
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Overwrite the default toggle behaviour and instead toggle this menu
|
|
||||||
Gui.core_defines.hide_top_flow:on_click(function(player, _, _)
|
|
||||||
Gui.toggle_left_element(player, toolbar_container)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Overwrite the default toggle behaviour and instead toggle this menu
|
|
||||||
Gui.core_defines.show_top_flow:on_click(function(player, _, _)
|
|
||||||
Gui.toggle_left_element(player, toolbar_container)
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Overwrite the default update top flow
|
|
||||||
local _update_top_flow = Gui.update_top_flow
|
|
||||||
function Gui.update_top_flow(player)
|
|
||||||
_update_top_flow(player) -- Call the original
|
|
||||||
|
|
||||||
local order = ToolbarState:get(player)
|
|
||||||
for index, state in ipairs(order) do
|
|
||||||
local element_define = Gui.defines[state.element_uid]
|
|
||||||
local top_element = Gui.get_top_element(player, element_define)
|
|
||||||
top_element.visible = top_element.visible and state.favourite or false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Uncompress the data to be more useable
|
|
||||||
ToolbarState:on_load(function(player_name, value)
|
|
||||||
-- If there is no value, do nothing
|
|
||||||
if value == nil then return end
|
|
||||||
|
|
||||||
-- Create a hash map of the favourites
|
|
||||||
local favourites = {}
|
|
||||||
for _, id in ipairs(value[2]) do
|
|
||||||
favourites[id] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Read the order from the value
|
|
||||||
local elements = {}
|
|
||||||
local element_hash = {}
|
|
||||||
for index, id in ipairs(value[1]) do
|
|
||||||
local element = datastore_id_map[id]
|
|
||||||
if element and not element_hash[element.uid] then
|
|
||||||
element_hash[element.uid] = true
|
|
||||||
elements[index] = {
|
|
||||||
element_uid = element.uid,
|
|
||||||
favourite = favourites[id] or false,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add any in the default state that are missing
|
|
||||||
for _, state in ipairs(toolbar_default_state) do
|
|
||||||
if not element_hash[state.element_uid] then
|
|
||||||
table.insert(elements, table.deep_copy(state))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create a hash map of the open left flows
|
|
||||||
local left_flows = {}
|
|
||||||
for _, id in ipairs(value[3]) do
|
|
||||||
local element = datastore_id_map[id]
|
|
||||||
if element.left_flow_element then
|
|
||||||
left_flows[element.left_flow_element] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the visible state of all left flows
|
|
||||||
local player = game.get_player(player_name)
|
|
||||||
for _, left_element in ipairs(Gui.left_elements) do
|
|
||||||
Gui.toggle_left_element(player, left_element, left_flows[left_element] or false)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the toolbar visible state
|
|
||||||
Gui.toggle_top_flow(player, value[4])
|
|
||||||
|
|
||||||
-- Set the data now and update now, ideally this would be on_update but that had too large of a latency
|
|
||||||
ToolbarState:raw_set(player_name, elements)
|
|
||||||
Gui.reorder_top_flow(player)
|
|
||||||
Gui.reorder_left_flow(player)
|
|
||||||
reorder_toolbar_menu(player)
|
|
||||||
|
|
||||||
return elements
|
|
||||||
end)
|
|
||||||
|
|
||||||
--- Save the current state of the players toolbar menu
|
|
||||||
ToolbarState:on_save(function(player_name, value)
|
|
||||||
if value == nil then return nil end -- Don't save default
|
|
||||||
local order, favourites, left_flows = {}, {}, {}
|
|
||||||
|
|
||||||
local player = game.get_player(player_name)
|
|
||||||
local top_flow_open = Gui.get_top_flow(player).parent.visible
|
|
||||||
|
|
||||||
for index, state in ipairs(value) do
|
|
||||||
-- Add the element to the order array
|
|
||||||
local element_define = Gui.defines[state.element_uid]
|
|
||||||
local id = to_datastore_id(element_define)
|
|
||||||
order[index] = id
|
|
||||||
|
|
||||||
-- If its a favourite then insert it
|
|
||||||
if state.favourite then
|
|
||||||
table.insert(favourites, id)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If it has a left flow and its open then insert it
|
|
||||||
if element_define.left_flow_element then
|
|
||||||
local left_element = Gui.get_left_element(player, element_define.left_flow_element)
|
|
||||||
if left_element.visible then
|
|
||||||
table.insert(left_flows, id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return { order, favourites, left_flows, top_flow_open }
|
|
||||||
end)
|
|
||||||
@@ -469,7 +469,7 @@ vlayer_container = Gui.element("vlayer_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(vlayer_container, false)
|
Gui.add_left_element(vlayer_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "vlayer_toggle",
|
name = "vlayer_toggle",
|
||||||
left_element = vlayer_container,
|
left_element = vlayer_container,
|
||||||
sprite = "entity/solar-panel",
|
sprite = "entity/solar-panel",
|
||||||
|
|||||||
@@ -703,7 +703,7 @@ warp_list_container = Gui.element("warp_list_container")
|
|||||||
|
|
||||||
--- Add the element to the left flow with a toolbar button
|
--- Add the element to the left flow with a toolbar button
|
||||||
Gui.add_left_element(warp_list_container, false)
|
Gui.add_left_element(warp_list_container, false)
|
||||||
Gui.create_toolbar_button{
|
Gui.toolbar.create_button{
|
||||||
name = "warp_list_toggle",
|
name = "warp_list_toggle",
|
||||||
left_element = warp_list_container,
|
left_element = warp_list_container,
|
||||||
sprite = config.default_icon.type .. "/" .. config.default_icon.name,
|
sprite = config.default_icon.type .. "/" .. config.default_icon.name,
|
||||||
@@ -714,7 +714,7 @@ Gui.create_toolbar_button{
|
|||||||
}:on_click(function(def, event, element)
|
}:on_click(function(def, event, element)
|
||||||
-- Set gui keep open state for player that clicked the button: true if visible, false if invisible
|
-- Set gui keep open state for player that clicked the button: true if visible, false if invisible
|
||||||
local player = Gui.get_player(event)
|
local player = Gui.get_player(event)
|
||||||
keep_gui_open[player.name] = Gui.get_toolbar_button_state(element)
|
keep_gui_open[player.name] = Gui.toolbar.get_button_toggled_state(def, player)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--- When the name of a warp is updated this is triggered
|
--- When the name of a warp is updated this is triggered
|
||||||
@@ -733,7 +733,7 @@ PlayerInRange:on_update(function(player_name, warp_id)
|
|||||||
|
|
||||||
-- Change if the frame is visible based on if the player is in range
|
-- Change if the frame is visible based on if the player is in range
|
||||||
if not keep_gui_open[player.name] then
|
if not keep_gui_open[player.name] then
|
||||||
Gui.set_left_element_visible(warp_list_container, player, warp_id ~= nil)
|
Gui.toolbar.set_left_element_visible_state(warp_list_container, player, warp_id ~= nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
update_all_warp_elements(player, nil, warp_id)
|
update_all_warp_elements(player, nil, warp_id)
|
||||||
|
|||||||
@@ -167,6 +167,18 @@ function ExpUtil.get_function_name(func, raw)
|
|||||||
return "<" .. file_name .. ":" .. func_name .. ">"
|
return "<" .. file_name .. ":" .. func_name .. ">"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns a desync sale filepath and current line for a given stack frame, default is the current file
|
||||||
|
--- @param level number? The level of the stack to get the file of, a value of 1 is the caller of this function
|
||||||
|
--- @param raw boolean? When true there will not be any < > around the name
|
||||||
|
--- @return string # The relative filepath of the given stack frame
|
||||||
|
function ExpUtil.get_current_line(level, raw)
|
||||||
|
local debug_info = getinfo((level or 1) + 1, "Snl")
|
||||||
|
local safe_source = debug_info.source:find("@__level__")
|
||||||
|
local file_path = safe_source == 1 and debug_info.short_src:sub(10, -5) or debug_info.source
|
||||||
|
if raw then return file_path .. ":" .. debug_info.currentline end
|
||||||
|
return "<" .. file_path .. ":" .. debug_info.currentline .. ">"
|
||||||
|
end
|
||||||
|
|
||||||
--- Attempt a simple autocomplete search from a set of options
|
--- Attempt a simple autocomplete search from a set of options
|
||||||
--- @param options table The table representing the possible options which can be selected
|
--- @param options table The table representing the possible options which can be selected
|
||||||
--- @param input string The user input string which should be matched to an option
|
--- @param input string The user input string which should be matched to an option
|
||||||
|
|||||||
Reference in New Issue
Block a user