267 lines
6.4 KiB
Lua
267 lines
6.4 KiB
Lua
local _M = {}
|
|
|
|
|
|
local MOD_NAME = 'crafting_combinator'
|
|
local LOCALE_CATEGORY = MOD_NAME..'_gui'
|
|
|
|
|
|
local function build_list(specs, root)
|
|
for _, spec in ipairs(specs) do
|
|
if type(spec) == 'table' then spec:build(root); end
|
|
end
|
|
return root
|
|
end
|
|
|
|
local function find_parent_name(parent)
|
|
if not parent then return nil; end
|
|
if parent.name ~= '' then return parent.name; end
|
|
return parent.parent and find_parent_name(parent.parent)
|
|
end
|
|
local function elem_name(parent, name)
|
|
local parent_name = find_parent_name(parent)
|
|
if parent_name and parent_name:match('^'..MOD_NAME) then return parent_name..':'..name
|
|
else return MOD_NAME..':'..name; end
|
|
end
|
|
local function locale(key) return {LOCALE_CATEGORY..'.'..key}; end
|
|
|
|
local function parse_common_options(options, name)
|
|
if type(options) == 'string' then options = {locale = options}; end
|
|
options = options or {}
|
|
|
|
options.locale_key = options.locale or name
|
|
options.locale = locale(options.locale_key)
|
|
if options.tooltip == true then options.tooltip = options.locale_key..':tooltip'; end
|
|
options.tooltip = options.tooltip and locale(options.tooltip)
|
|
|
|
return options
|
|
end
|
|
|
|
|
|
function _M.find_element(root, name)
|
|
for _, child in pairs(root.children) do
|
|
if child.name == '' then
|
|
local subresult = _M.find_element(child, name)
|
|
if subresult ~= nil then return subresult; end
|
|
elseif child.name == name then return child
|
|
elseif name:sub(1, #child.name) == child.name then return _M.find_element(child, name); end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
function _M.entity_name(entity) return entity.name:match('[^:]*$')..':'..tostring(entity.unit_number); end
|
|
|
|
function _M.name(...)
|
|
local args = table.pack(...)
|
|
local name = MOD_NAME
|
|
for i=1, args.n do
|
|
local step = args[i]
|
|
if type(step) == 'string' then name = name..':'..step
|
|
elseif type(step) == 'table' then
|
|
if type(step.__self) == 'userdata' then name = name..':'.._M.entity_name(step); end
|
|
end
|
|
end
|
|
return name
|
|
end
|
|
|
|
|
|
function _M.get_root(element) return game.get_player(element.player_index).gui.screen; end
|
|
|
|
|
|
function _M.parse_entity_gui_name(name)
|
|
local gui_name = name:gsub('^'..MOD_NAME..':', '')
|
|
local unit_number = gui_name:gsub('^.-:', '')
|
|
local element_name = unit_number:gsub('^.-:', '')
|
|
return gui_name:gsub(':.*$', ''), tonumber((unit_number:gsub(':.*$', ''))), element_name
|
|
end
|
|
|
|
|
|
function _M.open(spec, player_index, root)
|
|
local player = game.get_player(player_index)
|
|
local root = root or player.gui.screen
|
|
local element = spec:build(root)
|
|
player.opened = element
|
|
return element
|
|
end
|
|
|
|
|
|
function _M.entity(entity, specs)
|
|
specs.open = _M.open
|
|
|
|
local entity_name = entity.name:match('[^:]*$')
|
|
local unit_number = entity.unit_number
|
|
local entity_locale = entity.prototype.localised_name
|
|
|
|
function specs:build(root)
|
|
local main = root.add {
|
|
type = 'frame',
|
|
name = elem_name(root, entity_name..':'..tostring(unit_number)),
|
|
direction = 'vertical',
|
|
style = 'outer_frame',
|
|
}
|
|
main.auto_center = true
|
|
|
|
local title = main.add {
|
|
type = 'frame',
|
|
name = elem_name(main, 'title'),
|
|
caption = entity_locale,
|
|
direction = 'horizontal',
|
|
style = 'inner_frame_in_outer_frame',
|
|
}
|
|
local preview = title.add {
|
|
type = 'entity-preview',
|
|
name = elem_name(title, 'preview'),
|
|
style = 'entity_button_base',
|
|
}
|
|
preview.entity = entity
|
|
|
|
title.drag_target = main
|
|
|
|
if self.title_elements then
|
|
local title_container = title.add {
|
|
type = 'flow',
|
|
direction = 'vertical',
|
|
}
|
|
title_container.style.horizontal_align = 'right'
|
|
build_list(self.title_elements, title_container)
|
|
end
|
|
|
|
build_list(self, main)
|
|
|
|
return main
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.section(specs)
|
|
function specs:build(root)
|
|
local frame = root.add {
|
|
type = 'frame',
|
|
name = elem_name(root, specs.name),
|
|
caption = specs.caption or locale(specs.name),
|
|
direction = 'vertical',
|
|
}
|
|
if root.parent and root.parent == _M.get_root(root) and root.type == 'frame' then
|
|
frame.drag_target = root
|
|
end
|
|
|
|
build_list(self, frame)
|
|
|
|
return frame
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.spacer()
|
|
local specs = {}
|
|
function specs:build(root)
|
|
local res = root.add { type = 'flow' }
|
|
res.style.horizontally_stretchable = true
|
|
return res
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.checkbox(name, state, options)
|
|
options = parse_common_options(options, name)
|
|
local specs = {}
|
|
function specs:build(root)
|
|
return root.add {
|
|
type = 'checkbox',
|
|
name = elem_name(root, name),
|
|
caption = options.locale,
|
|
tooltip = options.tooltip,
|
|
state = state and true or false,
|
|
}
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.radio(name, selected, options)
|
|
options = parse_common_options(options, name)
|
|
local specs = {}
|
|
function specs:build(root)
|
|
return root.add {
|
|
type = 'radiobutton',
|
|
name = elem_name(root, name),
|
|
caption = options.locale,
|
|
tooltip = options.tooltip,
|
|
state = selected == name,
|
|
}
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.dropdown(name, items, selected, options)
|
|
options = parse_common_options(options, name)
|
|
local item_names = {}
|
|
for k, item in pairs(items) do item_names[k] = locale(options.locale_key..':'..item); end
|
|
|
|
local specs = {}
|
|
function specs:build(root)
|
|
local container = root.add {
|
|
type = 'flow',
|
|
name = elem_name(root, name),
|
|
direction = 'horizontal',
|
|
}
|
|
container.style.vertical_align = 'center'
|
|
container.add {
|
|
type = 'label',
|
|
name = elem_name(container, 'caption'),
|
|
caption = options.locale,
|
|
tooltip = options.tooltip,
|
|
}
|
|
container.add {
|
|
type = 'drop-down',
|
|
name = elem_name(container, 'value'),
|
|
items = item_names,
|
|
selected_index = selected,
|
|
}
|
|
return container
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.button(name)
|
|
local specs = {}
|
|
function specs:build(root)
|
|
return root.add {
|
|
type = 'button',
|
|
name = elem_name(root, name),
|
|
caption = locale(name),
|
|
mouse_button_filter = {'left'},
|
|
}
|
|
end
|
|
return specs
|
|
end
|
|
|
|
function _M.number_picker(name, value)
|
|
local specs = {}
|
|
function specs:build(root)
|
|
local container = root.add {
|
|
type = 'flow',
|
|
name = elem_name(root, name),
|
|
direction = 'horizontal',
|
|
}
|
|
container.style.vertical_align = 'center'
|
|
container.add {
|
|
type = 'label',
|
|
name = elem_name(container, 'caption'),
|
|
caption = locale(name),
|
|
}
|
|
local text_field = container.add {
|
|
type = 'textfield',
|
|
name = elem_name(container, 'value'),
|
|
text = tostring(value or 0),
|
|
numeric = true,
|
|
allow_negative = true,
|
|
allow_decimal = true,
|
|
}
|
|
text_field.style.width = 100
|
|
return container
|
|
end
|
|
return specs
|
|
end
|
|
|
|
|
|
return _M
|