385 lines
13 KiB
Lua
385 lines
13 KiB
Lua
local gui = require("__flib__/gui")
|
|
local math = require("__flib__/math")
|
|
|
|
local constants = require("__QuickItemSearch__/constants")
|
|
local logistic_request = require("__QuickItemSearch__/scripts/logistic-request")
|
|
|
|
local logistic_request_gui = {}
|
|
|
|
function logistic_request_gui.build(player, player_table)
|
|
if player.gui.screen.qis_request_window then
|
|
logistic_request_gui.destroy(player_table)
|
|
end
|
|
local resolution = player.display_resolution
|
|
local scale = player.display_scale
|
|
local focus_frame_size = { resolution.width / scale, resolution.height / scale }
|
|
|
|
local refs = gui.build(player.gui.screen, {
|
|
{
|
|
type = "frame",
|
|
style = "invisible_frame",
|
|
style_mods = { size = focus_frame_size },
|
|
ref = { "focus_frame" },
|
|
visible = false,
|
|
actions = {
|
|
on_click = { gui = "request", action = "close", reopen_after_subwindow = true },
|
|
},
|
|
},
|
|
{
|
|
type = "frame",
|
|
name = "qis_request_window",
|
|
direction = "vertical",
|
|
visible = false,
|
|
ref = { "window" },
|
|
actions = {
|
|
on_closed = { gui = "request", action = "close", reopen_after_subwindow = true },
|
|
},
|
|
children = {
|
|
{
|
|
type = "flow",
|
|
style = "flib_titlebar_flow",
|
|
ref = { "titlebar_flow" },
|
|
actions = {
|
|
on_click = { gui = "request", action = "recenter" },
|
|
},
|
|
children = {
|
|
{
|
|
type = "label",
|
|
style = "frame_title",
|
|
caption = { "gui.qis-edit-logistic-request" },
|
|
ignored_by_interaction = true,
|
|
},
|
|
{ type = "empty-widget", style = "flib_titlebar_drag_handle", ignored_by_interaction = true },
|
|
{
|
|
type = "sprite-button",
|
|
style = "frame_action_button",
|
|
sprite = "utility/close_white",
|
|
hovered_sprite = "utility/close_black",
|
|
clicked_sprite = "utility/close_black",
|
|
actions = {
|
|
on_click = { gui = "request", action = "close", reopen_after_subwindow = true },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
type = "frame",
|
|
style = "inside_shallow_frame",
|
|
direction = "vertical",
|
|
children = {
|
|
{
|
|
type = "frame",
|
|
style = "subheader_frame",
|
|
children = {
|
|
{ type = "label", style = "subheader_caption_label", ref = { "item_label" } },
|
|
{ type = "empty-widget", style = "flib_horizontal_pusher" },
|
|
},
|
|
},
|
|
{
|
|
type = "flow",
|
|
style_mods = { vertical_align = "center", horizontal_spacing = 8, padding = 12 },
|
|
children = {
|
|
{
|
|
type = "textfield",
|
|
style = "slider_value_textfield",
|
|
numeric = true,
|
|
clear_and_focus_on_right_click = true,
|
|
text = "0",
|
|
tags = { bound = "min" },
|
|
ref = { "logistic_setter", "min", "textfield" },
|
|
actions = {
|
|
on_confirmed = { gui = "request", action = "update_request" },
|
|
},
|
|
},
|
|
{
|
|
type = "flow",
|
|
direction = "vertical",
|
|
children = {
|
|
{
|
|
type = "slider",
|
|
style = "notched_slider",
|
|
style_mods = { horizontally_stretchable = true },
|
|
minimum_value = 0,
|
|
maximum_value = 500,
|
|
value_step = 50,
|
|
value = 0,
|
|
discrete_slider = true,
|
|
discrete_values = true,
|
|
tags = { bound = "max" },
|
|
ref = { "logistic_setter", "max", "slider" },
|
|
actions = {
|
|
on_value_changed = { gui = "request", action = "update_request" },
|
|
},
|
|
},
|
|
{
|
|
type = "slider",
|
|
style = "notched_slider",
|
|
style_mods = { horizontally_stretchable = true },
|
|
minimum_value = 0,
|
|
maximum_value = 500,
|
|
value_step = 50,
|
|
value = 500,
|
|
discrete_slider = true,
|
|
discrete_values = true,
|
|
tags = { bound = "min" },
|
|
ref = { "logistic_setter", "min", "slider" },
|
|
actions = {
|
|
on_value_changed = { gui = "request", action = "update_request" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
type = "textfield",
|
|
style = "slider_value_textfield",
|
|
numeric = true,
|
|
clear_and_focus_on_right_click = true,
|
|
text = constants.infinity_rep,
|
|
tags = { bound = "max" },
|
|
ref = { "logistic_setter", "max", "textfield" },
|
|
actions = {
|
|
on_confirmed = { gui = "request", action = "update_request" },
|
|
},
|
|
},
|
|
{
|
|
type = "sprite-button",
|
|
style = "item_and_count_select_confirm",
|
|
sprite = "utility/check_mark",
|
|
tooltip = { "", { "gui.qis-set-request" }, { "gui.qis-confirm" } },
|
|
ref = { "logistic_setter", "set_request_button" },
|
|
actions = {
|
|
on_click = { gui = "request", action = "set_request" },
|
|
},
|
|
},
|
|
{
|
|
type = "sprite-button",
|
|
style = "flib_tool_button_light_green",
|
|
style_mods = { top_margin = 1 },
|
|
sprite = "qis_temporary_request",
|
|
tooltip = { "", { "gui.qis-set-temporary-request" }, { "gui.qis-shift-confirm" } },
|
|
ref = { "logistic_setter", "set_temporary_request_button" },
|
|
actions = {
|
|
on_click = { gui = "request", action = "set_request", temporary = true },
|
|
},
|
|
},
|
|
{
|
|
type = "sprite-button",
|
|
style = "tool_button_red",
|
|
style_mods = { top_margin = 1 },
|
|
sprite = "utility/trash",
|
|
tooltip = { "", { "gui.qis-clear-request" }, { "gui.qis-control-confirm" } },
|
|
actions = {
|
|
on_click = { gui = "request", action = "clear_request" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
refs.window.force_auto_center()
|
|
refs.titlebar_flow.drag_target = refs.window
|
|
|
|
player_table.guis.request = {
|
|
refs = refs,
|
|
state = {
|
|
item_data = nil,
|
|
visible = false,
|
|
},
|
|
}
|
|
end
|
|
|
|
function logistic_request_gui.destroy(player_table)
|
|
local gui_data = player_table.guis.request
|
|
if not gui_data then
|
|
return
|
|
end
|
|
|
|
local window = gui_data.refs.window
|
|
if window and window.valid then
|
|
player_table.guis.request.refs.window.destroy()
|
|
end
|
|
player_table.guis.request = nil
|
|
end
|
|
|
|
function logistic_request_gui.open(player, player_table, item_data)
|
|
local gui_data = player_table.guis.request
|
|
local refs = gui_data.refs
|
|
local state = gui_data.state
|
|
|
|
-- update state
|
|
local stack_size = game.item_prototypes[item_data.name].stack_size
|
|
item_data.stack_size = stack_size
|
|
state.item_data = item_data
|
|
local request_data = item_data.request or { min = 0, max = math.max_uint }
|
|
state.request = request_data
|
|
state.visible = true
|
|
|
|
-- update item label
|
|
refs.item_label.caption = "[item=" .. item_data.name .. "] " .. item_data.translation
|
|
|
|
-- update logistic setter
|
|
local logistic_setter = refs.logistic_setter
|
|
for _, type in ipairs({ "min", "max" }) do
|
|
local elems = logistic_setter[type]
|
|
local count = request_data[type]
|
|
elems.textfield.enabled = true
|
|
if count >= math.max_uint then
|
|
elems.textfield.text = constants.infinity_rep
|
|
else
|
|
elems.textfield.text = tostring(count)
|
|
end
|
|
elems.slider.enabled = true
|
|
elems.slider.set_slider_value_step(1)
|
|
elems.slider.set_slider_minimum_maximum(0, stack_size * 10)
|
|
elems.slider.set_slider_value_step(stack_size)
|
|
elems.slider.slider_value = math.round(count / stack_size) * stack_size
|
|
end
|
|
refs.logistic_setter.min.textfield.select_all()
|
|
refs.logistic_setter.min.textfield.focus()
|
|
|
|
-- update window
|
|
refs.focus_frame.visible = true
|
|
refs.focus_frame.bring_to_front()
|
|
refs.window.visible = true
|
|
refs.window.bring_to_front()
|
|
|
|
-- set opened
|
|
player.opened = refs.window
|
|
end
|
|
|
|
function logistic_request_gui.close(player, player_table)
|
|
local gui_data = player_table.guis.request
|
|
gui_data.state.visible = false
|
|
gui_data.refs.focus_frame.visible = false
|
|
gui_data.refs.window.visible = false
|
|
if not player.opened then
|
|
player.opened = player_table.guis.search.refs.window
|
|
end
|
|
end
|
|
|
|
function logistic_request_gui.update_focus_frame_size(player, player_table)
|
|
local gui_data = player_table.guis.request
|
|
if gui_data then
|
|
local resolution = player.display_resolution
|
|
local scale = player.display_scale
|
|
local size = { resolution.width / scale, resolution.height / scale }
|
|
gui_data.refs.focus_frame.style.size = size
|
|
end
|
|
end
|
|
|
|
function logistic_request_gui.set_request(player, player_table, is_temporary, skip_sound)
|
|
if not skip_sound then
|
|
player.play_sound({ path = "utility/confirm" })
|
|
end
|
|
|
|
local gui_data = player_table.guis.request
|
|
local refs = gui_data.refs
|
|
local state = gui_data.state
|
|
|
|
-- get the latest values from each textfield
|
|
logistic_request_gui.update_request(refs, state, refs.logistic_setter.min.textfield)
|
|
logistic_request_gui.update_request(refs, state, refs.logistic_setter.max.textfield)
|
|
|
|
-- set the request
|
|
logistic_request.set(player, player_table, state.item_data.name, state.request, is_temporary)
|
|
|
|
-- close this window
|
|
if is_temporary then
|
|
player.opened = nil
|
|
end
|
|
end
|
|
|
|
function logistic_request_gui.clear_request(player, player_table)
|
|
player.play_sound({ path = "utility/confirm" })
|
|
logistic_request.clear(player, player_table, player_table.guis.request.state.item_data.name)
|
|
player.opened = nil
|
|
end
|
|
|
|
function logistic_request_gui.update_request(refs, state, element)
|
|
local item_data = state.item_data
|
|
local request_data = state.request
|
|
|
|
local bound = gui.get_tags(element).bound
|
|
|
|
local elems = refs.logistic_setter[bound]
|
|
local count
|
|
if element.type == "textfield" then
|
|
count = tonumber(element.text)
|
|
if count then
|
|
count = math.clamp(count, 0, math.max_uint)
|
|
else
|
|
count = bound == "min" and 0 or math.max_uint
|
|
end
|
|
elems.slider.slider_value = math.round(count / item_data.stack_size) * item_data.stack_size
|
|
else
|
|
count = element.slider_value
|
|
local text
|
|
if bound == "max" and count == item_data.stack_size * 10 then
|
|
count = math.max_uint
|
|
text = constants.infinity_rep
|
|
else
|
|
text = tostring(count)
|
|
end
|
|
elems.textfield.text = text
|
|
end
|
|
request_data[bound] = count
|
|
|
|
-- sync border
|
|
if bound == "min" and count > request_data.max then
|
|
request_data.max = count
|
|
refs.logistic_setter.max.textfield.text = tostring(count)
|
|
refs.logistic_setter.max.slider.slider_value = math.round(count / item_data.stack_size) * item_data.stack_size
|
|
elseif bound == "max" and count < request_data.min then
|
|
request_data.min = count
|
|
refs.logistic_setter.min.textfield.text = tostring(count)
|
|
refs.logistic_setter.min.slider.slider_value = math.round(count / item_data.stack_size) * item_data.stack_size
|
|
end
|
|
|
|
-- switch textfield
|
|
if element.type == "textfield" then
|
|
if bound == "min" then
|
|
refs.logistic_setter.max.textfield.select_all()
|
|
refs.logistic_setter.max.textfield.focus()
|
|
else
|
|
refs.logistic_setter.min.textfield.select_all()
|
|
refs.logistic_setter.min.textfield.focus()
|
|
end
|
|
end
|
|
end
|
|
|
|
function logistic_request_gui.handle_action(e, msg)
|
|
local player = game.get_player(e.player_index)
|
|
local player_table = global.players[e.player_index]
|
|
local gui_data = player_table.guis.request
|
|
local refs = gui_data.refs
|
|
local state = gui_data.state
|
|
|
|
if msg.action == "close" then
|
|
logistic_request_gui.close(player, player_table)
|
|
elseif msg.action == "bring_to_front" then
|
|
refs.window.bring_to_front()
|
|
elseif msg.action == "recenter" and e.button == defines.mouse_button_type.middle then
|
|
refs.window.force_auto_center()
|
|
elseif msg.action == "update_request" then
|
|
logistic_request_gui.update_request(refs, state, e.element)
|
|
elseif msg.action == "clear_request" then
|
|
logistic_request.clear(player, player_table, state.item_data.name)
|
|
-- invoke `on_gui_closed` so the search GUI will be refocused
|
|
player.opened = nil
|
|
elseif msg.action == "set_request" then
|
|
-- HACK: Makes it easy for the search GUI to tell that this was confirmed
|
|
player_table.confirmed_tick = game.ticks_played
|
|
logistic_request_gui.set_request(player, player_table, msg.temporary, true)
|
|
-- invoke `on_gui_closed` if the above function did not
|
|
if not msg.temporary then
|
|
player.opened = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
return logistic_request_gui
|