415 lines
13 KiB
Lua

local gui = require("__flib__.gui")
local table = require("__flib__.table")
local constants = require("constants")
local database = require("scripts.database")
local util = require("scripts.util")
--- @class SettingsGui
local Gui = {}
local actions = require("scripts.gui.settings.actions")
function Gui:dispatch(msg, e)
if type(msg) == "string" then
actions[msg](self, msg, e)
else
actions[msg.action](self, msg, e)
end
end
function Gui:destroy()
self.player_table.guis.settings.refs.window.destroy()
self.player_table.guis.settings = nil
end
function Gui:update_contents(tab)
local refs = self.refs
local state = self.state
local query = state.search_query
local translations = self.player_table.translations
local gui_translations = translations.gui
local actual_settings = self.player_table.settings
-- For simplicity's sake, since there's not _that much_ going on here, we will just destroy and recreate things
-- instead of updating them.
-- GENERAL
if not tab or tab == "general" then
local general_pane = refs.general.pane
general_pane.clear()
for category, settings in pairs(constants.general_settings) do
local actual_category_settings = actual_settings.general[category]
local children = {}
for setting_name, setting_ident in pairs(settings) do
local caption = gui_translations[setting_name] or setting_name
if string.find(string.lower(caption), query) then
local converted_setting_name = string.gsub(setting_name, "_", "-")
local tooltip = ""
if setting_ident.has_tooltip then
tooltip = { "gui.rb-" .. converted_setting_name .. "-description" }
caption = caption .. " [img=info]"
end
local enabled = true
if setting_ident.dependencies then
for _, dependency in pairs(setting_ident.dependencies) do
if actual_settings.general[dependency.category][dependency.name] ~= dependency.value then
enabled = false
break
end
end
end
if setting_ident.type == "bool" then
children[#children + 1] = {
type = "checkbox",
caption = caption,
tooltip = tooltip,
state = actual_category_settings[setting_name],
enabled = enabled,
actions = enabled and {
on_click = {
gui = "settings",
action = "change_general_setting",
type = setting_ident.type,
category = category,
name = setting_name,
},
} or nil,
}
elseif setting_ident.type == "enum" then
children[#children + 1] = {
type = "flow",
style_mods = { vertical_align = "center" },
{ type = "label", caption = caption, tooltip = tooltip },
{ type = "empty-widget", style = "flib_horizontal_pusher" },
{
type = "drop-down",
items = table.map(setting_ident.options, function(option_name)
return { "gui.rb-" .. converted_setting_name .. "-" .. string.gsub(option_name, "_", "-") }
end),
selected_index = table.find(setting_ident.options, actual_category_settings[setting_name]),
enabled = enabled,
actions = enabled and {
on_selection_state_changed = {
gui = "settings",
action = "change_general_setting",
type = setting_ident.type,
category = category,
name = setting_name,
},
} or nil,
},
}
end
end
end
if #children > 0 then
gui.build(general_pane, {
{
type = "frame",
style = "bordered_frame",
direction = "vertical",
caption = gui_translations[category] or category,
children = children,
},
})
end
end
end
-- CATEGORIES
if not tab or tab == "categories" then
local categories_frame = refs.categories.frame
categories_frame.clear()
local selected_class = constants.category_classes[state.selected_category]
local class_settings = actual_settings.categories[selected_class]
local class_translations = translations[selected_class]
local children = {}
for category_name in pairs(database[selected_class]) do
local category_translation = class_translations[category_name] or category_name
if string.find(string.lower(category_translation), query) then
local img_type = constants.class_to_type[selected_class]
if img_type then
category_translation = "[img=" .. img_type .. "/" .. category_name .. "] " .. category_translation
end
children[#children + 1] = {
type = "checkbox",
caption = category_translation,
state = class_settings[category_name],
actions = {
on_checked_state_changed = {
gui = "settings",
action = "change_category_setting",
class = selected_class,
name = category_name,
},
},
}
end
end
if #children > 0 then
gui.build(categories_frame, children)
end
end
-- PAGES
if not tab or tab == "pages" then
local pages_pane = refs.pages.pane
pages_pane.clear()
local selected_page = constants.pages_arr[state.selected_page]
local page_settings = actual_settings.pages[selected_page]
local children = {}
for component_name, component_settings in pairs(page_settings) do
local component_children = {}
component_children[1] = {
type = "flow",
style_mods = { vertical_align = "center" },
{ type = "label", caption = gui_translations.default_state },
{ type = "empty-widget", style = "flib_horizontal_pusher" },
{
type = "drop-down",
items = table.map(constants.component_states, function(option_name)
return { "gui.rb-" .. string.gsub(option_name, "_", "-") }
end),
selected_index = table.find(constants.component_states, component_settings.default_state),
actions = {
on_selection_state_changed = {
gui = "settings",
action = "change_default_state",
class = selected_page,
component = component_name,
},
},
},
}
if component_settings.max_rows then
component_children[#component_children + 1] = {
type = "flow",
style_mods = { vertical_align = "center" },
{ type = "label", caption = gui_translations.max_rows },
{ type = "empty-widget", style = "flib_horizontal_pusher" },
{
type = "textfield",
style_mods = { width = 50, horizontal_align = "center" },
numeric = true,
lose_focus_on_confirm = true,
clear_and_focus_on_right_click = true,
text = tostring(component_settings.max_rows),
actions = {
on_confirmed = {
gui = "settings",
action = "change_max_rows",
class = selected_page,
component = component_name,
},
},
},
}
end
if component_settings.rows then
for row_name, row_state in pairs(component_settings.rows) do
component_children[#component_children + 1] = {
type = "checkbox",
caption = gui_translations[row_name],
state = row_state,
actions = {
on_checked_state_changed = {
gui = "settings",
action = "change_row_visible",
class = selected_page,
component = component_name,
row = row_name,
},
},
}
end
end
children[#children + 1] = {
type = "frame",
style = "bordered_frame",
style_mods = { minimal_width = 300, horizontally_stretchable = true },
direction = "vertical",
caption = gui_translations[component_name] or component_name,
children = component_children,
}
end
gui.build(pages_pane, children)
end
end
local index = {}
local function subpage_set(name, action, include_tooltip, include_bordered_frame, initial_items)
return {
tab = {
type = "tab",
style_mods = { padding = { 7, 10, 8, 10 } },
caption = { "", { "gui.rb-" .. name }, include_tooltip and " [img=info]" or nil },
tooltip = include_tooltip and { "gui.rb-" .. name .. "-description" } or nil,
},
content = {
type = "flow",
style_mods = { horizontal_spacing = 12, padding = { 8, 0, 12, 12 } },
{
type = "list-box",
style = "list_box_in_shallow_frame",
style_mods = { height = 28 * constants.settings_gui_rows, width = 150 },
items = initial_items,
selected_index = 1,
actions = {
on_selection_state_changed = { gui = "settings", action = action },
},
},
{
type = "frame",
style = "flib_shallow_frame_in_shallow_frame",
style_mods = { height = 28 * constants.settings_gui_rows },
{
type = "scroll-pane",
style = "flib_naked_scroll_pane",
style_mods = { padding = 4, vertically_stretchable = true },
vertical_scroll_policy = "always",
ref = { name, "pane" },
include_bordered_frame and {
type = "frame",
style = "bordered_frame",
style_mods = { minimal_width = 300, horizontally_stretchable = true, vertically_stretchable = true },
direction = "vertical",
ref = { name, "frame" },
} or nil,
},
},
},
}
end
--- @param player LuaPlayer
--- @param player_table PlayerTable
function index.build(player, player_table)
local gui_translations = player_table.translations.gui
local refs = gui.build(player.gui.screen, {
{
type = "frame",
name = "rb_settings_window",
direction = "vertical",
ref = { "window" },
actions = {
on_closed = { gui = "settings", action = "close" },
},
{
type = "flow",
style = "flib_titlebar_flow",
ref = { "titlebar", "flow" },
actions = {
on_click = { gui = "settings", action = "reset_location" },
},
{ type = "label", style = "frame_title", caption = { "gui.rb-settings" }, ignored_by_interaction = true },
{ type = "empty-widget", style = "flib_titlebar_drag_handle", ignored_by_interaction = true },
{
type = "textfield",
style_mods = {
top_margin = -3,
right_padding = 3,
width = 120,
},
clear_and_focus_on_right_click = true,
visible = false,
ref = { "titlebar", "search_textfield" },
actions = {
on_text_changed = { gui = "settings", action = "update_search_query" },
},
},
util.frame_action_button(
"utility/search",
{ "gui.rb-search-instruction" },
{ "titlebar", "search_button" },
{ gui = "settings", action = "toggle_search" }
),
util.frame_action_button(
"utility/close",
{ "gui.close" },
{ "titlebar", "close_button" },
{ gui = "settings", action = "close" }
),
},
{
type = "frame",
style = "inside_deep_frame_for_tabs",
direction = "vertical",
{
type = "tabbed-pane",
style = "flib_tabbed_pane_with_no_padding",
{
tab = { type = "tab", caption = { "gui.rb-general" } },
content = {
type = "flow",
style_mods = { padding = 4 },
direction = "vertical",
ref = { "general", "pane" },
},
},
subpage_set(
"categories",
"change_category",
true,
true,
table.map(constants.category_classes, function(class)
return gui_translations[class] or class
end)
),
subpage_set(
"pages",
"change_page",
false,
false,
table.map(constants.pages_arr, function(class)
return gui_translations[class] or class
end)
),
},
},
},
})
refs.window.force_auto_center()
refs.titlebar.flow.drag_target = refs.window
player.opened = refs.window
--- @type SettingsGui
local self = {
player = player,
player_table = player_table,
refs = refs,
state = {
search_opened = false,
search_query = "",
selected_category = 1,
selected_page = 1,
},
}
index.load(self)
player_table.guis.settings = self
self:update_contents()
end
function index.load(self)
setmetatable(self, { __index = Gui })
end
return index