mirror of
https://github.com/Xevion/project-cybersyn.git
synced 2026-01-31 06:25:26 -06:00
merged gui
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 raiguard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,195 @@
|
||||
local train_util = require("__flib__.train")
|
||||
|
||||
local constants = require("scripts.gui.constants")
|
||||
|
||||
local util = require("scripts.gui.util")
|
||||
|
||||
local actions = {}
|
||||
|
||||
local function toggle_fab(elem, sprite, state)
|
||||
if state then
|
||||
elem.style = "flib_selected_frame_action_button"
|
||||
elem.sprite = sprite .. "_black"
|
||||
else
|
||||
elem.style = "frame_action_button"
|
||||
elem.sprite = sprite .. "_white"
|
||||
end
|
||||
end
|
||||
|
||||
function actions.close(Gui)
|
||||
Gui:close()
|
||||
end
|
||||
|
||||
function actions.recenter(Gui)
|
||||
Gui.refs.window.force_auto_center()
|
||||
end
|
||||
|
||||
function actions.toggle_auto_refresh(Gui)
|
||||
Gui.state.auto_refresh = not Gui.state.auto_refresh
|
||||
toggle_fab(Gui.refs.titlebar.refresh_button, "ltnm_refresh", Gui.state.auto_refresh)
|
||||
end
|
||||
|
||||
function actions.toggle_pinned(Gui)
|
||||
Gui.state.pinned = not Gui.state.pinned
|
||||
toggle_fab(Gui.refs.titlebar.pin_button, "ltnm_pin", Gui.state.pinned)
|
||||
|
||||
if Gui.state.pinned then
|
||||
Gui.state.pinning = true
|
||||
Gui.player.opened = nil
|
||||
Gui.state.pinning = false
|
||||
else
|
||||
Gui.player.opened = Gui.refs.window
|
||||
Gui.refs.window.force_auto_center()
|
||||
end
|
||||
end
|
||||
|
||||
function actions.update_text_search_query(Gui, _, e)
|
||||
local query = e.text
|
||||
-- Input sanitization
|
||||
for pattern, replacement in pairs(constants.input_sanitizers) do
|
||||
query = string.gsub(query, pattern, replacement)
|
||||
end
|
||||
Gui.state.search_query = query
|
||||
|
||||
if Gui.state.search_job then
|
||||
on_tick_n.remove(Gui.state.search_job)
|
||||
end
|
||||
|
||||
if #query == 0 then
|
||||
Gui:schedule_update()
|
||||
else
|
||||
Gui.state.search_job = on_tick_n.add(
|
||||
game.tick + 30,
|
||||
{ gui = "main", action = "update", player_index = Gui.player.index }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function actions.update_network_id_query(Gui)
|
||||
Gui.state.network_id = tonumber(Gui.refs.toolbar.network_id_field.text) or -1
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.open_train_gui(Gui, msg)
|
||||
local train_id = msg.train_id
|
||||
local train_data = Gui.state.ltn_data.trains[train_id]
|
||||
|
||||
if not train_data or not train_data.train.valid then
|
||||
util.error_flying_text(Gui.player, { "message.ltnm-error-train-is-invalid" })
|
||||
return
|
||||
end
|
||||
|
||||
train_util.open_gui(Gui.player.index, train_data.train)
|
||||
end
|
||||
|
||||
function actions.open_station_gui(Gui, msg, e)
|
||||
local station_id = msg.station_id
|
||||
local station_data = Gui.state.ltn_data.stations[station_id]
|
||||
|
||||
if not station_data or not station_data.entity.valid then
|
||||
util.error_flying_text(Gui.player, { "message.ltnm-error-station-is-invalid" })
|
||||
return
|
||||
end
|
||||
|
||||
--- @type LuaPlayer
|
||||
local player = Gui.player
|
||||
|
||||
if e.shift then
|
||||
player.zoom_to_world(station_data.entity.position, 1)
|
||||
|
||||
rendering.draw_circle({
|
||||
color = constants.colors.red.tbl,
|
||||
target = station_data.entity.position,
|
||||
surface = station_data.entity.surface,
|
||||
radius = 0.5,
|
||||
filled = false,
|
||||
width = 5,
|
||||
time_to_live = 60 * 3,
|
||||
players = { player },
|
||||
})
|
||||
|
||||
if not Gui.state.pinned then
|
||||
Gui:close()
|
||||
end
|
||||
elseif e.control and remote.interfaces["ltn-combinator"] then
|
||||
if not remote.call("ltn-combinator", "open_ltn_combinator", e.player_index, station_data.lamp_control, true) then
|
||||
util.error_flying_text(player, { "message.ltnm-error-ltn-combinator-not-found" })
|
||||
end
|
||||
else
|
||||
player.opened = station_data.entity
|
||||
end
|
||||
end
|
||||
|
||||
function actions.toggle_sort(Gui, msg, e)
|
||||
local tab = msg.tab
|
||||
local column = msg.column
|
||||
|
||||
local sorts = Gui.state.sorts[tab]
|
||||
local active_column = sorts._active
|
||||
if active_column == column then
|
||||
sorts[column] = e.element.state
|
||||
else
|
||||
sorts._active = column
|
||||
e.element.state = sorts[column]
|
||||
|
||||
local widths = Gui.widths[tab]
|
||||
|
||||
local old_checkbox = Gui.refs[tab].toolbar[active_column .. "_checkbox"]
|
||||
old_checkbox.style = "ltnm_sort_checkbox"
|
||||
if widths[active_column .. "_checkbox_stretchy"] then
|
||||
old_checkbox.style.horizontally_stretchable = true
|
||||
else
|
||||
old_checkbox.style.width = widths[active_column]
|
||||
end
|
||||
e.element.style = "ltnm_selected_sort_checkbox"
|
||||
if widths[column .. "_checkbox_stretchy"] then
|
||||
e.element.style.horizontally_stretchable = true
|
||||
else
|
||||
e.element.style.width = widths[column]
|
||||
end
|
||||
end
|
||||
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.update(Gui)
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.change_tab(Gui, msg)
|
||||
Gui.state.active_tab = msg.tab
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.change_surface(Gui, _, e)
|
||||
local selected_index = e.element.selected_index
|
||||
local selected_surface_index = Gui.state.ltn_data.surfaces.selected_to_index[selected_index]
|
||||
if selected_surface_index then
|
||||
Gui.state.surface = selected_surface_index
|
||||
Gui:schedule_update()
|
||||
end
|
||||
end
|
||||
|
||||
function actions.clear_history(Gui)
|
||||
global.flags.deleted_history = true
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.delete_alert(Gui, msg)
|
||||
global.active_data.alerts_to_delete[msg.alert_id] = true
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.delete_all_alerts(Gui)
|
||||
global.flags.deleted_all_alerts = true
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
function actions.focus_search(Gui)
|
||||
if not Gui.pinned then
|
||||
Gui.refs.toolbar.text_search_field.select_all()
|
||||
Gui.refs.toolbar.text_search_field.focus()
|
||||
end
|
||||
end
|
||||
|
||||
return actions
|
||||
@@ -0,0 +1,227 @@
|
||||
local gui = require("__flib__.gui")
|
||||
local misc = require("__flib__.misc")
|
||||
|
||||
local constants = require("constants")
|
||||
local util = require("scripts.util")
|
||||
|
||||
local templates = require("templates")
|
||||
|
||||
local alerts_tab = {}
|
||||
|
||||
function alerts_tab.build(widths)
|
||||
return {
|
||||
tab = {
|
||||
type = "tab",
|
||||
caption = { "gui.ltnm-alerts" },
|
||||
ref = { "alerts", "tab" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "change_tab", tab = "alerts" },
|
||||
},
|
||||
},
|
||||
content = {
|
||||
type = "frame",
|
||||
style = "ltnm_main_content_frame",
|
||||
direction = "vertical",
|
||||
ref = { "alerts", "content_frame" },
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_table_toolbar_frame",
|
||||
style_mods = { right_padding = 4 },
|
||||
templates.sort_checkbox(widths, "alerts", "time", true, nil, true),
|
||||
templates.sort_checkbox(widths, "alerts", "train_id", false),
|
||||
templates.sort_checkbox(widths, "alerts", "route", false),
|
||||
templates.sort_checkbox(widths, "alerts", "network_id", false),
|
||||
templates.sort_checkbox(nil, "alerts", "type", false),
|
||||
{
|
||||
type = "sprite-button",
|
||||
style = "tool_button_red",
|
||||
sprite = "utility/trash",
|
||||
tooltip = { "gui.ltnm-delete-all-alerts" },
|
||||
ref = { "alerts", "delete_all_button" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "delete_all_alerts" },
|
||||
},
|
||||
},
|
||||
},
|
||||
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "alerts", "scroll_pane" } },
|
||||
{
|
||||
type = "flow",
|
||||
style = "ltnm_warning_flow",
|
||||
visible = false,
|
||||
ref = { "alerts", "warning_flow" },
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_semibold_label",
|
||||
caption = { "gui.ltnm-no-alerts" },
|
||||
ref = { "alerts", "warning_label" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function alerts_tab.update(self)
|
||||
local dictionaries = self.player_table.dictionaries
|
||||
|
||||
local state = self.state
|
||||
local refs = self.refs.alerts
|
||||
local widths = self.widths
|
||||
|
||||
local search_query = state.search_query
|
||||
local search_network_id = state.network_id
|
||||
local search_surface = state.surface
|
||||
|
||||
local ltn_alerts = state.ltn_data.alerts
|
||||
local alerts_to_delete = global.active_data.alerts_to_delete
|
||||
|
||||
local scroll_pane = refs.scroll_pane
|
||||
local children = scroll_pane.children
|
||||
|
||||
local sorts = state.sorts[state.active_tab]
|
||||
local active_sort = sorts._active
|
||||
local sorted_alerts = state.ltn_data.sorted_alerts[active_sort]
|
||||
|
||||
local table_index = 0
|
||||
|
||||
-- False = ascending (arrow down), True = descending (arrow up)
|
||||
local start, finish, step
|
||||
if sorts[active_sort] then
|
||||
start = #sorted_alerts
|
||||
finish = 1
|
||||
step = -1
|
||||
else
|
||||
start = 1
|
||||
finish = #sorted_alerts
|
||||
step = 1
|
||||
end
|
||||
|
||||
if not global.flags.deleted_all_alerts then
|
||||
for sorted_index = start, finish, step do
|
||||
local alert_id = sorted_alerts[sorted_index]
|
||||
local alerts_entry = ltn_alerts[alert_id]
|
||||
|
||||
if
|
||||
(search_surface == -1 or (alerts_entry.train.surface_index == search_surface))
|
||||
and bit32.btest(alerts_entry.train.network_id, search_network_id)
|
||||
and (#search_query == 0 or string.find(
|
||||
alerts_entry.search_strings[self.player.index] or "",
|
||||
string.lower(search_query)
|
||||
))
|
||||
and not alerts_to_delete[alert_id]
|
||||
then
|
||||
table_index = table_index + 1
|
||||
local row = children[table_index]
|
||||
local color = table_index % 2 == 0 and "dark" or "light"
|
||||
if not row then
|
||||
row = gui.add(scroll_pane, {
|
||||
type = "frame",
|
||||
style = "ltnm_table_row_frame_" .. color,
|
||||
{ type = "label", style_mods = { width = widths.alerts.time } },
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.alerts.train_id, horizontal_align = "center" },
|
||||
tooltip = { "gui.ltnm-open-train-gui" },
|
||||
},
|
||||
{
|
||||
type = "flow",
|
||||
style_mods = { vertical_spacing = 0 },
|
||||
direction = "vertical",
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.alerts.route },
|
||||
tooltip = constants.open_station_gui_tooltip,
|
||||
},
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.alerts.route },
|
||||
tooltip = constants.open_station_gui_tooltip,
|
||||
},
|
||||
},
|
||||
{ type = "label", style_mods = { width = widths.alerts.network_id, horizontal_align = "center" } },
|
||||
{ type = "label", style_mods = { width = widths.alerts.type } },
|
||||
{
|
||||
type = "frame",
|
||||
name = "contents_frame",
|
||||
style = "ltnm_small_slot_table_frame_" .. color,
|
||||
style_mods = { width = widths.alerts.contents },
|
||||
{ type = "table", name = "contents_table", style = "slot_table", column_count = 4 },
|
||||
},
|
||||
{
|
||||
type = "sprite-button",
|
||||
style = "tool_button_red",
|
||||
sprite = "utility/trash",
|
||||
tooltip = { "gui.ltnm-delete-alert" },
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
gui.update(row, {
|
||||
{ elem_mods = { caption = misc.ticks_to_timestring(alerts_entry.time) } },
|
||||
{
|
||||
elem_mods = { caption = alerts_entry.train_id },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_train_gui", train_id = alerts_entry.train_id },
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
elem_mods = { caption = alerts_entry.train.from },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_station_gui", station_id = alerts_entry.train.from_id },
|
||||
},
|
||||
},
|
||||
{
|
||||
elem_mods = {
|
||||
caption = "[color=" .. constants.colors.caption.str .. "]->[/color] " .. alerts_entry.train.to,
|
||||
},
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_station_gui", station_id = alerts_entry.train.to_id },
|
||||
},
|
||||
},
|
||||
},
|
||||
{ elem_mods = { caption = util.signed_int32(alerts_entry.train.network_id) } },
|
||||
{
|
||||
elem_mods = {
|
||||
caption = { "gui.ltnm-alert-" .. string.gsub(alerts_entry.type, "_", "-") },
|
||||
tooltip = { "gui.ltnm-alert-" .. string.gsub(alerts_entry.type, "_", "-") .. "-description" },
|
||||
},
|
||||
},
|
||||
{},
|
||||
{
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "delete_alert", alert_id = alert_id },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
util.slot_table_update(row.contents_frame.contents_table, {
|
||||
{ color = "green", entries = alerts_entry.planned_shipment or {}, translations = dictionaries.materials },
|
||||
{ color = "red", entries = alerts_entry.actual_shipment or {}, translations = dictionaries.materials },
|
||||
{ color = "red", entries = alerts_entry.unscheduled_load or {}, translations = dictionaries.materials },
|
||||
{ color = "red", entries = alerts_entry.remaining_load or {}, translations = dictionaries.materials },
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for child_index = table_index + 1, #children do
|
||||
children[child_index].destroy()
|
||||
end
|
||||
|
||||
if table_index == 0 then
|
||||
refs.warning_flow.visible = true
|
||||
scroll_pane.visible = false
|
||||
refs.content_frame.style = "ltnm_main_warning_frame"
|
||||
refs.delete_all_button.enabled = false
|
||||
else
|
||||
refs.warning_flow.visible = false
|
||||
scroll_pane.visible = true
|
||||
refs.content_frame.style = "ltnm_main_content_frame"
|
||||
refs.delete_all_button.enabled = true
|
||||
end
|
||||
end
|
||||
|
||||
return alerts_tab
|
||||
@@ -0,0 +1,152 @@
|
||||
local constants = {}
|
||||
|
||||
constants.colors = {
|
||||
caption = {
|
||||
str = "255, 230, 192",
|
||||
tbl = { 255, 230, 192 },
|
||||
},
|
||||
green = {
|
||||
str = "69, 255, 69",
|
||||
tbl = { 69, 255, 69 },
|
||||
},
|
||||
info = {
|
||||
str = "128, 206, 240",
|
||||
tbl = { 128, 206, 240 },
|
||||
},
|
||||
red = {
|
||||
str = "255, 69, 69",
|
||||
tbl = { 255, 69, 69 },
|
||||
},
|
||||
station_circle = {
|
||||
str = "255, 50, 50, 190",
|
||||
tbl = { 255, 50, 50, 190 },
|
||||
},
|
||||
yellow = {
|
||||
str = "255, 240, 69",
|
||||
tbl = { 255, 240, 69 },
|
||||
},
|
||||
white = {
|
||||
str = "255, 255, 255",
|
||||
tbl = { 255, 255, 255 },
|
||||
},
|
||||
}
|
||||
|
||||
-- dictionary locale identifier -> dictionary of hardcoded GUI sizes
|
||||
constants.gui = {
|
||||
en = {
|
||||
trains = {
|
||||
train_id = 90,
|
||||
status = 378,
|
||||
composition = 200,
|
||||
depot = 149,
|
||||
shipment = 36 * 6,
|
||||
shipment_columns = 6,
|
||||
},
|
||||
stations = {
|
||||
name = 238,
|
||||
status = 53,
|
||||
network_id = 84,
|
||||
provided_requested = 36 * 6,
|
||||
provided_requested_columns = 6,
|
||||
shipments = 36 * 5,
|
||||
shipments_columns = 5,
|
||||
control_signals = 36 * 7,
|
||||
control_signals_columns = 7,
|
||||
},
|
||||
depots = {
|
||||
name = 200,
|
||||
network_id = 84,
|
||||
status = 200,
|
||||
trains = 200,
|
||||
},
|
||||
history = {
|
||||
train_id = 60,
|
||||
route = 357,
|
||||
depot = 160,
|
||||
network_id = 84,
|
||||
runtime = 68,
|
||||
finished = 68,
|
||||
shipment = (36 * 6),
|
||||
shipment_checkbox_stretchy = true,
|
||||
},
|
||||
alerts = {
|
||||
time = 68,
|
||||
train_id = 60,
|
||||
route = 326,
|
||||
network_id = 84,
|
||||
type = 230,
|
||||
type_checkbox_stretchy = true,
|
||||
contents = 36 * 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
constants.gui_content_frame_height = 744
|
||||
constants.gui_inventory_table_height = 40 * 18
|
||||
|
||||
constants.gui_translations = {
|
||||
delivering_to = { "gui.ltnm-delivering-to" },
|
||||
fetching_from = { "gui.ltnm-fetching-from" },
|
||||
loading_at = { "gui.ltnm-loading-at" },
|
||||
not_available = { "gui.ltnm-not-available" },
|
||||
parked_at_depot_with_residue = { "gui.ltnm-parked-at-depot-with-residue" },
|
||||
parked_at_depot = { "gui.ltnm-parked-at-depot" },
|
||||
returning_to_depot = { "gui.ltnm-returning-to-depot" },
|
||||
unloading_at = { "gui.ltnm-unloading-at" },
|
||||
}
|
||||
|
||||
constants.input_sanitizers = {
|
||||
["%%"] = "%%%%",
|
||||
["%("] = "%%(",
|
||||
["%)"] = "%%)",
|
||||
["%.^[%*]"] = "%%.",
|
||||
["%+"] = "%%+",
|
||||
["%-"] = "%%-",
|
||||
["^[%.]%*"] = "%%*",
|
||||
["%?"] = "%%?",
|
||||
["%["] = "%%[",
|
||||
["%]"] = "%%]",
|
||||
["%^"] = "%%^",
|
||||
["%$"] = "%%$",
|
||||
}
|
||||
|
||||
constants.ltn_control_signals = {
|
||||
["ltn-depot"] = true,
|
||||
["ltn-depot-priority"] = true,
|
||||
-- excluded because it's shown as a separate column
|
||||
-- ["ltn-network-id"] = true,
|
||||
["ltn-min-train-length"] = true,
|
||||
["ltn-max-train-length"] = true,
|
||||
["ltn-max-trains"] = true,
|
||||
["ltn-provider-threshold"] = true,
|
||||
["ltn-provider-stack-threshold"] = true,
|
||||
["ltn-provider-priority"] = true,
|
||||
["ltn-locked-slots"] = true,
|
||||
["ltn-requester-threshold"] = true,
|
||||
["ltn-requester-stack-threshold"] = true,
|
||||
["ltn-requester-priority"] = true,
|
||||
["ltn-disable-warnings"] = true,
|
||||
}
|
||||
|
||||
constants.ltn_event_names = {
|
||||
on_stops_updated = true,
|
||||
on_dispatcher_updated = true,
|
||||
-- on_delivery_pickup_complete = true,
|
||||
on_delivery_completed = true,
|
||||
on_delivery_failed = true,
|
||||
-- on_dispatcher_no_train_found = true,
|
||||
on_provider_missing_cargo = true,
|
||||
on_provider_unscheduled_cargo = true,
|
||||
on_requester_remaining_cargo = true,
|
||||
on_requester_unscheduled_cargo = true,
|
||||
}
|
||||
|
||||
if script then
|
||||
constants.open_station_gui_tooltip = {
|
||||
"",
|
||||
{ "gui.ltnm-open-station-gui" },
|
||||
remote.interfaces["ltn-combinator"] and { "", "\n", { "gui.ltnm-open-ltn-combinator-gui" } } or nil,
|
||||
}
|
||||
end
|
||||
|
||||
return constants
|
||||
@@ -0,0 +1,144 @@
|
||||
local gui = require("__flib__.gui")
|
||||
|
||||
local templates = require("templates")
|
||||
|
||||
local depots_tab = {}
|
||||
|
||||
function depots_tab.build(widths)
|
||||
return {
|
||||
tab = {
|
||||
type = "tab",
|
||||
caption = { "gui.ltnm-depots" },
|
||||
ref = { "depots", "tab" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "change_tab", tab = "depots" },
|
||||
},
|
||||
},
|
||||
content = {
|
||||
type = "frame",
|
||||
style = "ltnm_main_content_frame",
|
||||
direction = "vertical",
|
||||
ref = { "depots", "content_frame" },
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_table_toolbar_frame",
|
||||
style_mods = { right_padding = 4 },
|
||||
templates.sort_checkbox(widths, "depots", "name", true, nil, true),
|
||||
templates.sort_checkbox(widths, "depots", "network_id", false),
|
||||
templates.sort_checkbox(widths, "depots", "status", false, { "gui.ltnm-status-description" }),
|
||||
templates.sort_checkbox(widths, "depots", "trains", false),
|
||||
},
|
||||
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "depots", "scroll_pane" } },
|
||||
{
|
||||
type = "flow",
|
||||
style = "ltnm_warning_flow",
|
||||
visible = false,
|
||||
ref = { "depots", "warning_flow" },
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_semibold_label",
|
||||
caption = { "gui.ltnm-no-depots" },
|
||||
ref = { "depots", "warning_label" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function depots_tab.update(self)
|
||||
local state = self.state
|
||||
local refs = self.refs.depots
|
||||
local widths = self.widths.depots
|
||||
|
||||
local search_query = state.search_query
|
||||
local search_network_id = state.network_id
|
||||
local search_surface = state.surface
|
||||
|
||||
local ltn_depots = state.ltn_data.depots
|
||||
local scroll_pane = refs.scroll_pane
|
||||
local children = scroll_pane.children
|
||||
|
||||
local sorts = state.sorts.depots
|
||||
local active_sort = sorts._active
|
||||
local sorted_depots = state.ltn_data.sorted_depots[active_sort]
|
||||
|
||||
local table_index = 0
|
||||
|
||||
-- False = ascending (arrow down), True = descending (arrow up)
|
||||
local start, finish, step
|
||||
if sorts[active_sort] then
|
||||
start = #sorted_depots
|
||||
finish = 1
|
||||
step = -1
|
||||
else
|
||||
start = 1
|
||||
finish = #sorted_depots
|
||||
step = 1
|
||||
end
|
||||
|
||||
for sorted_index = start, finish, step do
|
||||
local depot_name = sorted_depots[sorted_index]
|
||||
local depot_data = ltn_depots[depot_name]
|
||||
|
||||
if
|
||||
(search_surface == -1 or depot_data.surfaces[search_surface])
|
||||
and bit32.btest(depot_data.network_id, search_network_id)
|
||||
and (#search_query == 0 or string.find(depot_data.search_string, string.lower(search_query)))
|
||||
then
|
||||
table_index = table_index + 1
|
||||
local row = children[table_index]
|
||||
local color = table_index % 2 == 0 and "dark" or "light"
|
||||
if not row then
|
||||
row = gui.add(scroll_pane, {
|
||||
type = "frame",
|
||||
style = "ltnm_table_row_frame_" .. color,
|
||||
{ type = "label", style_mods = { width = widths.name } },
|
||||
{ type = "label", style_mods = { width = widths.network_id, horizontal_align = "center" } },
|
||||
{ type = "flow", name = "statuses_flow", style_mods = { width = widths.status } },
|
||||
{ type = "label", style_mods = { width = widths.trains } },
|
||||
})
|
||||
end
|
||||
|
||||
gui.update(row, {
|
||||
{ elem_mods = { caption = depot_name } },
|
||||
{ elem_mods = { caption = depot_data.network_id } },
|
||||
{},
|
||||
{ elem_mods = { caption = depot_data.trains_string } },
|
||||
})
|
||||
|
||||
local statuses_flow = row.statuses_flow
|
||||
local statuses_children = statuses_flow.children
|
||||
local status_index = 0
|
||||
for color, count in pairs(depot_data.statuses) do
|
||||
status_index = status_index + 1
|
||||
local status_flow = statuses_children[status_index]
|
||||
if not status_flow then
|
||||
status_flow = gui.add(statuses_flow, templates.status_indicator())
|
||||
end
|
||||
gui.update(status_flow, {
|
||||
{ elem_mods = { sprite = "flib_indicator_" .. color } },
|
||||
{ elem_mods = { caption = count } },
|
||||
})
|
||||
end
|
||||
for child_index = status_index + 1, #statuses_children do
|
||||
statuses_children[child_index].destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for child_index = table_index + 1, #children do
|
||||
children[child_index].destroy()
|
||||
end
|
||||
|
||||
if table_index == 0 then
|
||||
refs.warning_flow.visible = true
|
||||
scroll_pane.visible = false
|
||||
refs.content_frame.style = "ltnm_main_warning_frame"
|
||||
else
|
||||
refs.warning_flow.visible = false
|
||||
scroll_pane.visible = true
|
||||
refs.content_frame.style = "ltnm_main_content_frame"
|
||||
end
|
||||
end
|
||||
|
||||
return depots_tab
|
||||
@@ -0,0 +1,208 @@
|
||||
local gui = require("__flib__.gui")
|
||||
local misc = require("__flib__.misc")
|
||||
|
||||
local constants = require("constants")
|
||||
local util = require("scripts.util")
|
||||
|
||||
local templates = require("templates")
|
||||
|
||||
local history_tab = {}
|
||||
|
||||
function history_tab.build(widths)
|
||||
return {
|
||||
tab = {
|
||||
type = "tab",
|
||||
caption = { "gui.ltnm-history" },
|
||||
ref = { "history", "tab" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "change_tab", tab = "history" },
|
||||
},
|
||||
},
|
||||
content = {
|
||||
type = "frame",
|
||||
style = "ltnm_main_content_frame",
|
||||
direction = "vertical",
|
||||
ref = { "history", "content_frame" },
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_table_toolbar_frame",
|
||||
style_mods = { right_padding = 4 },
|
||||
templates.sort_checkbox(widths, "history", "train_id", false),
|
||||
templates.sort_checkbox(widths, "history", "route", false),
|
||||
templates.sort_checkbox(widths, "history", "depot", false),
|
||||
templates.sort_checkbox(widths, "history", "network_id", false),
|
||||
templates.sort_checkbox(widths, "history", "runtime", false),
|
||||
templates.sort_checkbox(widths, "history", "finished", true, nil, true),
|
||||
templates.sort_checkbox(nil, "history", "shipment", false),
|
||||
{
|
||||
type = "sprite-button",
|
||||
style = "tool_button_red",
|
||||
sprite = "utility/trash",
|
||||
tooltip = { "gui.ltnm-clear-history" },
|
||||
ref = { "history", "clear_button" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "clear_history" },
|
||||
},
|
||||
},
|
||||
},
|
||||
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "history", "scroll_pane" } },
|
||||
{
|
||||
type = "flow",
|
||||
style = "ltnm_warning_flow",
|
||||
visible = false,
|
||||
ref = { "history", "warning_flow" },
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_semibold_label",
|
||||
caption = { "gui.ltnm-no-history" },
|
||||
ref = { "history", "warning_label" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function history_tab.update(self)
|
||||
local dictionaries = self.player_table.dictionaries
|
||||
|
||||
local state = self.state
|
||||
local refs = self.refs.history
|
||||
local widths = self.widths
|
||||
|
||||
local search_query = state.search_query
|
||||
local search_network_id = state.network_id
|
||||
local search_surface = state.surface
|
||||
|
||||
local ltn_history = state.ltn_data.history
|
||||
local scroll_pane = refs.scroll_pane
|
||||
local children = scroll_pane.children
|
||||
|
||||
local sorts = state.sorts[state.active_tab]
|
||||
local active_sort = sorts._active
|
||||
local sorted_history = state.ltn_data.sorted_history[active_sort]
|
||||
|
||||
local table_index = 0
|
||||
|
||||
-- False = ascending (arrow down), True = descending (arrow up)
|
||||
local start, finish, step
|
||||
if sorts[active_sort] then
|
||||
start = #sorted_history
|
||||
finish = 1
|
||||
step = -1
|
||||
else
|
||||
start = 1
|
||||
finish = #sorted_history
|
||||
step = 1
|
||||
end
|
||||
|
||||
if not global.flags.deleted_history then
|
||||
for sorted_index = start, finish, step do
|
||||
local history_id = sorted_history[sorted_index]
|
||||
local history_entry = ltn_history[history_id]
|
||||
|
||||
if
|
||||
(search_surface == -1 or (history_entry.surface_index == search_surface))
|
||||
and bit32.btest(history_entry.network_id, search_network_id)
|
||||
and (
|
||||
#search_query == 0 or string.find(history_entry.search_strings[self.player.index], string.lower(search_query))
|
||||
)
|
||||
then
|
||||
table_index = table_index + 1
|
||||
local row = children[table_index]
|
||||
local color = table_index % 2 == 0 and "dark" or "light"
|
||||
if not row then
|
||||
row = gui.add(scroll_pane, {
|
||||
type = "frame",
|
||||
style = "ltnm_table_row_frame_" .. color,
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.history.train_id, horizontal_align = "center" },
|
||||
tooltip = constants.open_station_gui_tooltip,
|
||||
},
|
||||
{
|
||||
type = "flow",
|
||||
style_mods = { vertical_spacing = 0 },
|
||||
direction = "vertical",
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.history.route },
|
||||
tooltip = constants.open_station_gui_tooltip,
|
||||
},
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.history.route },
|
||||
tooltip = constants.open_station_gui_tooltip,
|
||||
},
|
||||
},
|
||||
{ type = "label", style_mods = { width = widths.history.depot } },
|
||||
{ type = "label", style_mods = { width = widths.history.network_id, horizontal_align = "center" } },
|
||||
{ type = "label", style_mods = { width = widths.history.finished, horizontal_align = "center" } },
|
||||
{ type = "label", style_mods = { width = widths.history.runtime, horizontal_align = "center" } },
|
||||
{
|
||||
type = "frame",
|
||||
name = "shipment_frame",
|
||||
style = "ltnm_small_slot_table_frame_" .. color,
|
||||
style_mods = { width = widths.history.shipment },
|
||||
{ type = "table", name = "shipment_table", style = "slot_table", column_count = 4 },
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
gui.update(row, {
|
||||
{
|
||||
elem_mods = { caption = history_entry.train_id },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_train_gui", train_id = history_entry.train_id },
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
elem_mods = { caption = history_entry.from },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_station_gui", station_id = history_entry.from_id },
|
||||
},
|
||||
},
|
||||
{
|
||||
elem_mods = {
|
||||
caption = "[color=" .. constants.colors.caption.str .. "]->[/color] " .. history_entry.to,
|
||||
},
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_station_gui", station_id = history_entry.to_id },
|
||||
},
|
||||
},
|
||||
},
|
||||
{ elem_mods = { caption = history_entry.depot } },
|
||||
{ elem_mods = { caption = util.signed_int32(history_entry.network_id) } },
|
||||
{ elem_mods = { caption = misc.ticks_to_timestring(history_entry.runtime) } },
|
||||
{ elem_mods = { caption = misc.ticks_to_timestring(history_entry.finished) } },
|
||||
})
|
||||
|
||||
util.slot_table_update(
|
||||
row.shipment_frame.shipment_table,
|
||||
{ { color = "default", entries = history_entry.shipment, translations = dictionaries.materials } }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for child_index = table_index + 1, #children do
|
||||
children[child_index].destroy()
|
||||
end
|
||||
|
||||
if table_index == 0 then
|
||||
refs.warning_flow.visible = true
|
||||
scroll_pane.visible = false
|
||||
refs.content_frame.style = "ltnm_main_warning_frame"
|
||||
refs.clear_button.enabled = false
|
||||
else
|
||||
refs.warning_flow.visible = false
|
||||
scroll_pane.visible = true
|
||||
refs.content_frame.style = "ltnm_main_content_frame"
|
||||
refs.clear_button.enabled = true
|
||||
end
|
||||
end
|
||||
|
||||
return history_tab
|
||||
@@ -0,0 +1,87 @@
|
||||
local misc = require("__flib__.misc")
|
||||
|
||||
local templates = require("templates")
|
||||
|
||||
local inventory_tab = {}
|
||||
|
||||
function inventory_tab.build()
|
||||
return {
|
||||
tab = {
|
||||
type = "tab",
|
||||
caption = { "gui.ltnm-inventory" },
|
||||
ref = { "inventory", "tab" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "change_tab", tab = "inventory" },
|
||||
},
|
||||
},
|
||||
content = {
|
||||
type = "flow",
|
||||
style_mods = { horizontal_spacing = 12 },
|
||||
direction = "horizontal",
|
||||
ref = { "inventory", "content_frame" },
|
||||
templates.inventory_slot_table("provided", 12),
|
||||
templates.inventory_slot_table("in_transit", 8),
|
||||
templates.inventory_slot_table("requested", 6),
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function update_table(self, name, color)
|
||||
local translations = self.player_table.dictionaries.materials
|
||||
|
||||
local state = self.state
|
||||
local refs = self.refs.inventory
|
||||
|
||||
local search_query = state.search_query
|
||||
local search_network_id = state.network_id
|
||||
local search_surface = state.surface
|
||||
|
||||
local ltn_inventory = state.ltn_data.inventory[name][search_surface]
|
||||
|
||||
local i = 0
|
||||
|
||||
local table = refs[name].table
|
||||
local children = table.children
|
||||
|
||||
for name, count_by_network_id in pairs(ltn_inventory or {}) do
|
||||
if
|
||||
bit32.btest(count_by_network_id.combined_id, search_network_id)
|
||||
and string.find(string.lower(translations[name]), string.lower(search_query))
|
||||
then
|
||||
local running_count = 0
|
||||
for network_id, count in pairs(count_by_network_id) do
|
||||
if network_id ~= "combined_id" and bit32.btest(network_id, search_network_id) then
|
||||
running_count = running_count + count
|
||||
end
|
||||
end
|
||||
|
||||
if running_count > 0 then
|
||||
i = i + 1
|
||||
local button = children[i]
|
||||
if not button then
|
||||
button = table.add({ type = "sprite-button", style = "flib_slot_button_" .. color, enabled = false })
|
||||
end
|
||||
button.sprite = string.gsub(name, ",", "/")
|
||||
button.number = running_count
|
||||
button.tooltip = "[img="
|
||||
.. string.gsub(name, ",", "/")
|
||||
.. "] [font=default-semibold]"
|
||||
.. translations[name]
|
||||
.. "[/font]\n"
|
||||
.. misc.delineate_number(running_count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for j = i + 1, #children do
|
||||
children[j].destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function inventory_tab.update(self)
|
||||
update_table(self, "provided", "green")
|
||||
update_table(self, "in_transit", "blue")
|
||||
update_table(self, "requested", "red")
|
||||
end
|
||||
|
||||
return inventory_tab
|
||||
@@ -0,0 +1,270 @@
|
||||
local gui = require("__flib__.gui-lite")
|
||||
|
||||
local constants = require("scripts.gui.constants")
|
||||
|
||||
--local actions = require("scripts.gui.actions")
|
||||
local templates = require("scripts.gui.templates")
|
||||
|
||||
local trains_tab = require("scripts.gui.trains")
|
||||
--local depots_tab = require("scripts.gui.depots")
|
||||
--local stations_tab = require("scripts.gui.stations")
|
||||
--local inventory_tab = require("scripts.gui.inventory")
|
||||
--local history_tab = require("scripts.gui.history")
|
||||
--local alerts_tab = require("scripts.gui.alerts")
|
||||
|
||||
|
||||
function Index:dispatch(msg, e)
|
||||
-- "Transform" the action based on criteria
|
||||
if msg.transform == "handle_refresh_click" then
|
||||
if e.shift then
|
||||
msg.action = "toggle_auto_refresh"
|
||||
else
|
||||
self.state.ltn_data = global.data
|
||||
self.do_update = true
|
||||
end
|
||||
elseif msg.transform == "handle_titlebar_click" then
|
||||
if e.button == defines.mouse_button_type.middle then
|
||||
msg.action = "recenter"
|
||||
end
|
||||
end
|
||||
|
||||
-- Dispatch the associated action
|
||||
if msg.action then
|
||||
local func = self.actions[msg.action]
|
||||
if func then
|
||||
func(self, msg, e)
|
||||
else
|
||||
log("Attempted to call action `" .. msg.action .. "` for which there is no handler yet.")
|
||||
end
|
||||
end
|
||||
|
||||
-- Update if necessary
|
||||
if self.do_update then
|
||||
self:update()
|
||||
self.do_update = false
|
||||
end
|
||||
end
|
||||
|
||||
function Index:schedule_update()
|
||||
self.do_update = true
|
||||
end
|
||||
|
||||
|
||||
local manager = {}
|
||||
|
||||
|
||||
function manager.build(player, player_data)
|
||||
local widths = constants.gui["en"]
|
||||
---@type table<string, LuaGuiElement>
|
||||
local refs = {}
|
||||
|
||||
local _, window = gui.add(player.gui.screen, {
|
||||
{
|
||||
name = "manager_window",
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
visible = false,
|
||||
handler = manager_handle.close,
|
||||
children = {
|
||||
{
|
||||
name = "manager_titlebar",
|
||||
type = "flow",
|
||||
style = "flib_titlebar_flow",
|
||||
handler = manager_handle.titlebar_click,
|
||||
children = {
|
||||
{ type = "label", style = "frame_title", caption = { "mod-name.LtnManager" }, ignored_by_interaction = true },
|
||||
{ type = "empty-widget", style = "flib_titlebar_drag_handle", ignored_by_interaction = true },
|
||||
{
|
||||
name = "manager_dispatcher_status_label",
|
||||
type = "label",
|
||||
style = "bold_label",
|
||||
style_mods = { font_color = constants.colors.red.tbl, left_margin = -4, top_margin = 1 },
|
||||
caption = { "gui.ltnm-dispatcher-disabled" },
|
||||
tooltip = { "gui.ltnm-dispatcher-disabled-description" },
|
||||
visible = not settings.global["cybersyn-enable-planner"].value,
|
||||
},
|
||||
templates.frame_action_button("manager_pin_button", "ltnm_pin", { "gui.ltnm-keep-open" }, manager_handle.pin),--on_gui_clicked
|
||||
templates.frame_action_button("manager_refresh_button", "ltnm_refresh", { "gui.ltnm-refresh-tooltip" }, manager_handle.refresh_click),--on_gui_clicked
|
||||
templates.frame_action_button(nil, "utility/close", { "gui.close-instruction" }, manager_handle.close),--on_gui_clicked
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "frame",
|
||||
style = "inside_deep_frame",
|
||||
direction = "vertical",
|
||||
children = {
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_main_toolbar_frame",
|
||||
children = {
|
||||
{ type = "label", style = "subheader_caption_label", caption = { "gui.ltnm-search-label" } },
|
||||
{
|
||||
name = "manager_text_search_field",
|
||||
type = "textfield",
|
||||
clear_and_focus_on_right_click = true,
|
||||
handler = manager_handle.update_text_search_query, --on_gui_text_changed
|
||||
},
|
||||
{ type = "empty-widget", style = "flib_horizontal_pusher" },
|
||||
{ type = "label", style = "caption_label", caption = { "gui.ltnm-network-id-label" } },
|
||||
{
|
||||
name = "manager_network_id_field",
|
||||
type = "textfield",
|
||||
style_mods = { width = 120 },
|
||||
numeric = true,
|
||||
allow_negative = true,
|
||||
clear_and_focus_on_right_click = true,
|
||||
text = "-1",
|
||||
handler = manager_handle.update_network_id_query, --on_gui_text_changed
|
||||
},
|
||||
{ type = "label", style = "caption_label", caption = { "gui.ltnm-surface-label" } },
|
||||
{
|
||||
name = "manager_surface_dropdown",
|
||||
type = "drop-down",
|
||||
handler = manager_handle.change_surface, --on_gui_selection_state_changed
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "manager_tabbed_pane",
|
||||
type = "tabbed-pane",
|
||||
style = "ltnm_tabbed_pane",
|
||||
children = {
|
||||
trains_tab.build(widths, refs),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, refs)
|
||||
|
||||
|
||||
|
||||
refs.manager_titlebar.drag_target = window
|
||||
window.force_auto_center()
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.destroy(player, refs)
|
||||
refs.manager_window.destroy()
|
||||
|
||||
player.set_shortcut_toggled("ltnm-toggle-gui", false)
|
||||
player.set_shortcut_available("ltnm-toggle-gui", false)
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.open(player, player_data, refs)
|
||||
refs.manager_window.bring_to_front()
|
||||
refs.manager_window.visible = true
|
||||
player_data.visible = true
|
||||
|
||||
if not player_data.pinning then
|
||||
player.opened = refs.manager_window
|
||||
end
|
||||
|
||||
player.set_shortcut_toggled("ltnm-toggle-gui", true)
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.close(player, player_data, refs)
|
||||
if player_data.pinning then
|
||||
return
|
||||
end
|
||||
|
||||
refs.manager_window.visible = false
|
||||
player_data.visible = false
|
||||
|
||||
if player.opened == refs.manager_window then
|
||||
player.opened = nil
|
||||
end
|
||||
|
||||
player.set_shortcut_toggled("ltnm-toggle-gui", false)
|
||||
end
|
||||
|
||||
|
||||
manager.handle = {}
|
||||
|
||||
--- @param e GuiEventData
|
||||
function manager.wrapper(e, handler)
|
||||
local player = game.get_player(e.player_index)
|
||||
if not player then return end
|
||||
local player_data = global.manager.players[e.player_index]
|
||||
handler(player, player_data, refs)
|
||||
end
|
||||
|
||||
|
||||
local function toggle_fab(elem, sprite, state)
|
||||
if state then
|
||||
elem.style = "flib_selected_frame_action_button"
|
||||
elem.sprite = sprite .. "_black"
|
||||
else
|
||||
elem.style = "frame_action_button"
|
||||
elem.sprite = sprite .. "_white"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
manager.handle.close = manager.close
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.handle.recenter(player, player_data, refs)
|
||||
refs.window.force_auto_center()
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.handle.toggle_auto_refresh(player, player_data, refs)
|
||||
player_data.auto_refresh = not player_data.auto_refresh
|
||||
toggle_fab(refs.manager_refresh_button, "ltnm_refresh", player_data.auto_refresh)
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.handle.toggle_pinned(player, player_data, refs)
|
||||
player_data.pinned = not player_data.pinned
|
||||
toggle_fab(refs.manager_pin_button, "ltnm_pin", player_data.pinned)
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.handle.update_text_search_query(player, player_data, refs)
|
||||
local query = e.text
|
||||
-- Input sanitization
|
||||
for pattern, replacement in pairs(constants.input_sanitizers) do
|
||||
query = string.gsub(query, pattern, replacement)
|
||||
end
|
||||
Gui.state.search_query = query
|
||||
|
||||
if Gui.state.search_job then
|
||||
on_tick_n.remove(Gui.state.search_job)
|
||||
end
|
||||
|
||||
if #query == 0 then
|
||||
Gui:schedule_update()
|
||||
else
|
||||
Gui.state.search_job = on_tick_n.add(
|
||||
game.tick + 30,
|
||||
{ gui = "main", action = "update", player_index = Gui.player.index }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
--- @param player LuaPlayer
|
||||
--- @param player_data PlayerData
|
||||
--- @param refs table<string, LuaGuiElement>
|
||||
function manager.handle.update_network_id_query(player, player_data, refs)
|
||||
Gui.state.network_id = tonumber(Gui.refs.toolbar.network_id_field.text) or -1
|
||||
Gui:schedule_update()
|
||||
end
|
||||
|
||||
return manager
|
||||
@@ -0,0 +1,174 @@
|
||||
local gui = require("__flib__.gui")
|
||||
|
||||
local constants = require("constants")
|
||||
|
||||
local util = require("scripts.util")
|
||||
|
||||
local templates = require("templates")
|
||||
|
||||
local stations_tab = {}
|
||||
|
||||
function stations_tab.build(widths)
|
||||
return {
|
||||
tab = {
|
||||
type = "tab",
|
||||
caption = { "gui.ltnm-stations" },
|
||||
ref = { "stations", "tab" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "change_tab", tab = "stations" },
|
||||
},
|
||||
},
|
||||
content = {
|
||||
type = "frame",
|
||||
style = "ltnm_main_content_frame",
|
||||
direction = "vertical",
|
||||
ref = { "stations", "content_frame" },
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_table_toolbar_frame",
|
||||
templates.sort_checkbox(widths, "stations", "name", true),
|
||||
templates.sort_checkbox(widths, "stations", "status", false, { "gui.ltnm-status-description" }),
|
||||
templates.sort_checkbox(widths, "stations", "network_id", false),
|
||||
templates.sort_checkbox(
|
||||
widths,
|
||||
"stations",
|
||||
"provided_requested",
|
||||
false,
|
||||
{ "gui.ltnm-provided-requested-description" }
|
||||
),
|
||||
templates.sort_checkbox(widths, "stations", "shipments", false, { "gui.ltnm-shipments-description" }),
|
||||
templates.sort_checkbox(widths, "stations", "control_signals", false),
|
||||
},
|
||||
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "stations", "scroll_pane" } },
|
||||
{
|
||||
type = "flow",
|
||||
style = "ltnm_warning_flow",
|
||||
visible = false,
|
||||
ref = { "stations", "warning_flow" },
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_semibold_label",
|
||||
caption = { "gui.ltnm-no-stations" },
|
||||
ref = { "stations", "warning_label" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function stations_tab.update(self)
|
||||
local dictionaries = self.player_table.dictionaries
|
||||
|
||||
local state = self.state
|
||||
local refs = self.refs.stations
|
||||
local widths = self.widths.stations
|
||||
|
||||
local search_query = state.search_query
|
||||
local search_network_id = state.network_id
|
||||
local search_surface = state.surface
|
||||
|
||||
local ltn_stations = state.ltn_data.stations
|
||||
local scroll_pane = refs.scroll_pane
|
||||
local children = scroll_pane.children
|
||||
|
||||
local sorts = state.sorts.stations
|
||||
local active_sort = sorts._active
|
||||
local sorted_stations = state.ltn_data.sorted_stations[active_sort]
|
||||
|
||||
local table_index = 0
|
||||
|
||||
-- False = ascending (arrow down), True = descending (arrow up)
|
||||
local start, finish, step
|
||||
if sorts[active_sort] then
|
||||
start = #sorted_stations
|
||||
finish = 1
|
||||
step = -1
|
||||
else
|
||||
start = 1
|
||||
finish = #sorted_stations
|
||||
step = 1
|
||||
end
|
||||
|
||||
for sorted_index = start, finish, step do
|
||||
local station_id = sorted_stations[sorted_index]
|
||||
local station_data = ltn_stations[station_id]
|
||||
|
||||
if station_data.entity.valid then
|
||||
if
|
||||
(search_surface == -1 or station_data.entity.surface.index == search_surface)
|
||||
and bit32.btest(station_data.network_id, search_network_id)
|
||||
and (
|
||||
#search_query == 0 or string.find(station_data.search_strings[self.player.index], string.lower(search_query))
|
||||
)
|
||||
then
|
||||
table_index = table_index + 1
|
||||
local row = children[table_index]
|
||||
local color = table_index % 2 == 0 and "dark" or "light"
|
||||
if not row then
|
||||
row = gui.add(scroll_pane, {
|
||||
type = "frame",
|
||||
style = "ltnm_table_row_frame_" .. color,
|
||||
{
|
||||
type = "label",
|
||||
style = "ltnm_clickable_semibold_label",
|
||||
style_mods = { width = widths.name },
|
||||
tooltip = constants.open_station_gui_tooltip,
|
||||
},
|
||||
templates.status_indicator(widths.status, true),
|
||||
{ type = "label", style_mods = { width = widths.network_id, horizontal_align = "center" } },
|
||||
templates.small_slot_table(widths, color, "provided_requested"),
|
||||
templates.small_slot_table(widths, color, "shipments"),
|
||||
templates.small_slot_table(widths, color, "control_signals"),
|
||||
})
|
||||
end
|
||||
|
||||
gui.update(row, {
|
||||
{
|
||||
elem_mods = { caption = station_data.name },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_station_gui", station_id = station_id },
|
||||
},
|
||||
},
|
||||
{
|
||||
{ elem_mods = { sprite = "flib_indicator_" .. station_data.status.color } },
|
||||
{ elem_mods = { caption = station_data.status.count } },
|
||||
},
|
||||
{ elem_mods = { caption = station_data.network_id } },
|
||||
})
|
||||
|
||||
util.slot_table_update(row.provided_requested_frame.provided_requested_table, {
|
||||
{ color = "green", entries = station_data.provided, translations = dictionaries.materials },
|
||||
{ color = "red", entries = station_data.requested, translations = dictionaries.materials },
|
||||
})
|
||||
util.slot_table_update(row.shipments_frame.shipments_table, {
|
||||
{ color = "green", entries = station_data.inbound, translations = dictionaries.materials },
|
||||
{ color = "blue", entries = station_data.outbound, translations = dictionaries.materials },
|
||||
})
|
||||
util.slot_table_update(row.control_signals_frame.control_signals_table, {
|
||||
{
|
||||
color = "default",
|
||||
entries = station_data.control_signals,
|
||||
translations = dictionaries.virtual_signals,
|
||||
type = "virtual-signal",
|
||||
},
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for child_index = table_index + 1, #children do
|
||||
children[child_index].destroy()
|
||||
end
|
||||
|
||||
if table_index == 0 then
|
||||
refs.warning_flow.visible = true
|
||||
scroll_pane.visible = false
|
||||
refs.content_frame.style = "ltnm_main_warning_frame"
|
||||
else
|
||||
refs.warning_flow.visible = false
|
||||
scroll_pane.visible = true
|
||||
refs.content_frame.style = "ltnm_main_content_frame"
|
||||
end
|
||||
end
|
||||
|
||||
return stations_tab
|
||||
@@ -0,0 +1,100 @@
|
||||
local constants = require("constants")
|
||||
|
||||
local templates = {}
|
||||
|
||||
--- Creates a frame action button, automatically accounting for inverted sprites.
|
||||
--- @param name string?
|
||||
--- @param sprite string?
|
||||
--- @param tooltip LocalisedString?
|
||||
--- @param handler GuiElemHandler?
|
||||
--- @param tags Tags?
|
||||
function templates.frame_action_button(name, sprite, tooltip, handler, tags)
|
||||
return {
|
||||
type = "sprite-button",
|
||||
name = name,
|
||||
style = "frame_action_button",
|
||||
sprite = sprite .. "_white",
|
||||
hovered_sprite = sprite .. "_black",
|
||||
clicked_sprite = sprite .. "_black",
|
||||
mouse_button_filter = { "left" },
|
||||
tooltip = tooltip,
|
||||
handler = handler,
|
||||
tags = tags,
|
||||
}
|
||||
end
|
||||
|
||||
--- Creates a full-sized scrollable slot table for the inventory tab.
|
||||
--- @param name string
|
||||
--- @param columns uint
|
||||
function templates.inventory_slot_table(name, columns)
|
||||
return {
|
||||
type = "flow",
|
||||
direction = "vertical",
|
||||
{ type = "label", style = "bold_label", caption = { "gui.ltnm-" .. string.gsub(name, "_", "-") } },
|
||||
{
|
||||
type = "frame",
|
||||
style = "deep_frame_in_shallow_frame",
|
||||
style_mods = { height = constants.gui_inventory_table_height },
|
||||
ref = { "inventory", name, "frame" },
|
||||
{
|
||||
type = "scroll-pane",
|
||||
style = "ltnm_slot_table_scroll_pane",
|
||||
style_mods = { width = 40 * columns + 12, minimal_height = constants.gui_inventory_table_height },
|
||||
vertical_scroll_policy = "auto-and-reserve-space",
|
||||
-- vertical_scroll_policy = "always",
|
||||
ref = { "inventory", name, "scroll_pane" },
|
||||
{ type = "table", style = "slot_table", column_count = columns, ref = { "inventory", name, "table" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
--- Creates a small non-scrollable slot table.
|
||||
--- @param widths table
|
||||
--- @param color string
|
||||
--- @param name string
|
||||
function templates.small_slot_table(widths, color, name)
|
||||
return {
|
||||
type = "frame",
|
||||
name = name .. "_frame",
|
||||
style = "ltnm_small_slot_table_frame_" .. color,
|
||||
style_mods = { width = widths[name] },
|
||||
{ type = "table", name = name .. "_table", style = "slot_table", column_count = widths[name .. "_columns"] },
|
||||
}
|
||||
end
|
||||
|
||||
--- Creates a column header with a sort toggle.
|
||||
--- @param widths table
|
||||
--- @param tab string
|
||||
--- @param column string
|
||||
--- @param selected boolean
|
||||
--- @param tooltip LocalisedString
|
||||
function templates.sort_checkbox(widths, tab, column, selected, tooltip, state)
|
||||
if state == nil then
|
||||
state = false
|
||||
end
|
||||
return {
|
||||
type = "checkbox",
|
||||
style = selected and "ltnm_selected_sort_checkbox" or "ltnm_sort_checkbox",
|
||||
style_mods = { width = widths and widths[tab][column] or nil, horizontally_stretchable = not widths },
|
||||
caption = { "gui.ltnm-" .. string.gsub(column, "_", "-") },
|
||||
tooltip = tooltip,
|
||||
state = state,
|
||||
ref = { tab, "toolbar", column .. "_checkbox" },
|
||||
actions = {
|
||||
on_checked_state_changed = { gui = "main", tab = tab, action = "toggle_sort", column = column },
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
function templates.status_indicator(width, center)
|
||||
return {
|
||||
type = "flow",
|
||||
style = "flib_indicator_flow",
|
||||
style_mods = { horizontal_align = center and "center" or nil, width = width },
|
||||
{ type = "sprite", style = "flib_indicator" },
|
||||
{ type = "label" },
|
||||
}
|
||||
end
|
||||
|
||||
return templates
|
||||
@@ -0,0 +1,151 @@
|
||||
local gui = require("__flib__.gui-lite")
|
||||
|
||||
local constants = require("constants")
|
||||
local util = require("scripts.gui.util")
|
||||
|
||||
local templates = require("templates")
|
||||
|
||||
local trains_tab = {}
|
||||
|
||||
|
||||
function trains_tab.build(map_data, player_id, player_data)
|
||||
local widths = constants.gui["en"]
|
||||
|
||||
local search_query = player_data.search_query
|
||||
local search_network_flag = player_data.network_flag
|
||||
local search_network = player_data.network
|
||||
|
||||
local trains_sorted = player_data.trains_sorted
|
||||
|
||||
---@type GuiElemDef
|
||||
local train_list = {}
|
||||
--if not sorted_trains then
|
||||
-- sorted_trains = {}
|
||||
-- ids = {}
|
||||
-- for id, train in pairs(map_data) do
|
||||
-- local i = #ids + 1
|
||||
-- ids[i] = id
|
||||
-- sorted_trains[i] = train
|
||||
-- end
|
||||
-- dual_sort(ids, sorted_trains)
|
||||
--end
|
||||
if #trains_sorted == 0 then
|
||||
train_list[1] = {
|
||||
type = "label",
|
||||
style = "ltnm_semibold_label",
|
||||
caption = { "gui.ltnm-no-trains" },
|
||||
ref = { "trains", "warning_label" },
|
||||
}
|
||||
else
|
||||
local start, finish, step
|
||||
if player_data.trains_ascending then
|
||||
start = #trains_sorted
|
||||
finish = 1
|
||||
step = -1
|
||||
else
|
||||
start = 1
|
||||
finish = #trains_sorted
|
||||
step = 1
|
||||
end
|
||||
|
||||
local gui_idx = 1
|
||||
for idx = start, finish, step do
|
||||
local train_id = trains_sorted[idx]
|
||||
local train = map_data.trains[train_id]
|
||||
|
||||
if
|
||||
true
|
||||
then
|
||||
local color = gui_idx % 2 == 0 and "dark" or "light"
|
||||
train_list[gui_idx] = {
|
||||
type = "frame",
|
||||
style = "ltnm_table_row_frame_" .. color,
|
||||
children = {
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_table_inset_frame_" .. color,
|
||||
children = {
|
||||
type = "minimap",
|
||||
style = "ltnm_train_minimap",
|
||||
{ type = "label", style = "ltnm_minimap_label" },
|
||||
{
|
||||
type = "button",
|
||||
style = "ltnm_train_minimap_button",
|
||||
tooltip = { "gui.ltnm-open-train-gui" },
|
||||
elem_mods = { entity = get_any_train_entity(train.entity) },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "open_train_gui", train_id = train_id },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type = "label",
|
||||
style_mods = { width = widths.trains.composition },
|
||||
elem_mods = { caption = train.composition },
|
||||
},
|
||||
{
|
||||
type = "label", style_mods = { width = widths.trains.depot },
|
||||
elem_mods = { caption = train.depot },
|
||||
},
|
||||
{
|
||||
type = "frame",
|
||||
name = "shipment_frame",
|
||||
style = "ltnm_small_slot_table_frame_" .. color,
|
||||
style_mods = { width = widths.trains.shipment },
|
||||
children = {
|
||||
{
|
||||
type = "table",
|
||||
name = "shipment_table",
|
||||
style = "slot_table",
|
||||
column_count = widths.trains.shipment_columns,
|
||||
children = util.slot_table_build(train.manifest, "default"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
gui_idx = gui_idx + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
tab = {
|
||||
type = "tab",
|
||||
caption = #trains_sorted == 0 and { "gui.ltnm-trains" } or { "gui.ltnm-trains", #train_list },
|
||||
badge_text = misc.delineate_number(#ltn_data.sorted_trains.composition),
|
||||
ref = { "trains", "tab" },
|
||||
actions = {
|
||||
on_click = { gui = "main", action = "change_tab", tab = "trains" },
|
||||
},
|
||||
},
|
||||
content = {
|
||||
type = "frame",
|
||||
style = "ltnm_main_content_frame",
|
||||
direction = "vertical",
|
||||
ref = { "trains", "content_frame" },
|
||||
children = {
|
||||
{
|
||||
type = "frame",
|
||||
style = "ltnm_table_toolbar_frame",
|
||||
templates.sort_checkbox(widths, "trains", "train_id", true),
|
||||
templates.sort_checkbox(widths, "trains", "status", false),
|
||||
templates.sort_checkbox(widths, "trains", "composition", false, { "gui.ltnm-composition-description" }),
|
||||
templates.sort_checkbox(widths, "trains", "depot", false),
|
||||
templates.sort_checkbox(widths, "trains", "shipment", false),
|
||||
},
|
||||
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "trains", "scroll_pane" } },
|
||||
{
|
||||
type = "flow",
|
||||
style = "ltnm_warning_flow",
|
||||
visible = false,
|
||||
ref = { "trains", "warning_flow" },
|
||||
children = train_list,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
return trains_tab
|
||||
@@ -0,0 +1,90 @@
|
||||
local gui = require("__flib__.gui-lite")
|
||||
local format = require("__flib__.format")
|
||||
|
||||
local util = {}
|
||||
|
||||
--- Create a flying text at the player's cursor with an error sound.
|
||||
--- @param player LuaPlayer
|
||||
--- @param message LocalisedString
|
||||
function util.error_flying_text(player, message)
|
||||
player.create_local_flying_text({ create_at_cursor = true, text = message })
|
||||
player.play_sound({ path = "utility/cannot_build" })
|
||||
end
|
||||
|
||||
function util.gui_list(parent, iterator, test, build, update, ...)
|
||||
local children = parent.children
|
||||
local i = 0
|
||||
|
||||
for k, v in table.unpack(iterator) do
|
||||
local passed = test(v, k, i, ...)
|
||||
if passed then
|
||||
i = i + 1
|
||||
local child = children[i]
|
||||
if not child then
|
||||
gui.build(parent, { build(...) })
|
||||
child = parent.children[i]
|
||||
end
|
||||
gui.update(child, update(v, k, i, ...))
|
||||
end
|
||||
end
|
||||
|
||||
for j = i + 1, #children do
|
||||
children[j].destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--- Updates a slot table based on the passed criteria.
|
||||
--- @param manifest Manifest
|
||||
--- @param color string
|
||||
--- @return GuiElemDef[]
|
||||
function util.slot_table_build(manifest, color)
|
||||
local children = {}
|
||||
local i = 1
|
||||
for _, item in pairs(manifest) do
|
||||
local name = item.name
|
||||
local sprite
|
||||
if item.type then
|
||||
sprite = item.type .. "/" .. name
|
||||
else
|
||||
sprite = string.gsub(name, ",", "/")
|
||||
end
|
||||
if game.is_valid_sprite_path(sprite) then
|
||||
children[i] = {
|
||||
type = "sprite-button",
|
||||
enabled = false,
|
||||
style = "ltnm_small_slot_button_" .. color,
|
||||
sprite = sprite,
|
||||
tooltip = {
|
||||
"",
|
||||
"[img=" .. sprite .. "]",
|
||||
{ "item-name." .. name },
|
||||
"\n"..format.number(count),
|
||||
},
|
||||
}
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return children
|
||||
end
|
||||
|
||||
function util.sorted_iterator(arr, src_tbl, sort_state)
|
||||
local step = sort_state and 1 or -1
|
||||
local i = sort_state and 1 or #arr
|
||||
|
||||
return function()
|
||||
local j = i + step
|
||||
if arr[j] then
|
||||
i = j
|
||||
local arr_value = arr[j]
|
||||
return arr_value, src_tbl[arr_value]
|
||||
end
|
||||
end,
|
||||
arr
|
||||
end
|
||||
|
||||
local MAX_INT = 2147483648 -- math.pow(2, 31)
|
||||
function util.signed_int32(val)
|
||||
return (val >= MAX_INT and val - (2 * MAX_INT)) or val
|
||||
end
|
||||
|
||||
return util
|
||||
Reference in New Issue
Block a user