666 lines
28 KiB
Lua
666 lines
28 KiB
Lua
require("ui.base.view_state")
|
|
|
|
-- The main GUI parts for the compact dialog
|
|
-- ** LOCAL UTIL **
|
|
local function determine_available_columns(lines, frame_width)
|
|
local frame_border_size = 12
|
|
local table_padding, table_spacing = 8, 12
|
|
local recipe_and_check_width = 58
|
|
local button_width, button_spacing = 36, 4
|
|
|
|
local max_module_count = 0
|
|
for _, line in pairs(lines) do
|
|
if line.subfloor == nil then
|
|
local module_kinds = ModuleSet.get_module_kind_amount(line.machine.module_set)
|
|
max_module_count = math.max(max_module_count, module_kinds)
|
|
end
|
|
if line.beacon ~= nil then
|
|
local module_kinds = ModuleSet.get_module_kind_amount(line.beacon.module_set)
|
|
max_module_count = math.max(max_module_count, module_kinds)
|
|
end
|
|
end
|
|
|
|
local used_width = 0
|
|
used_width = used_width + (frame_border_size * 2) -- border on both sides
|
|
used_width = used_width + (table_padding * 2) -- padding on both sides
|
|
used_width = used_width + (table_spacing * 4) -- 5 columns -> 4 spaces
|
|
used_width = used_width + recipe_and_check_width -- constant
|
|
-- Add up machines button, module buttons, and spacing for them
|
|
used_width = used_width + button_width + (max_module_count * button_width) + (max_module_count * button_spacing)
|
|
|
|
-- Calculate the remaining width and divide by the amount a button takes up
|
|
local available_columns = (frame_width - used_width + button_spacing) / (button_width + button_spacing)
|
|
return math.floor(available_columns) -- amount is floored as to not cause a horizontal scrollbar
|
|
end
|
|
|
|
local function determine_table_height(lines, column_counts)
|
|
local total_height = 0
|
|
for _, line in pairs(lines) do
|
|
local items_height = 0
|
|
for column, count in pairs(column_counts) do
|
|
local column_height = math.ceil(line[column].count / count)
|
|
items_height = math.max(items_height, column_height)
|
|
end
|
|
|
|
local machines_height = (line.beacon ~= nil) and 2 or 1
|
|
total_height = total_height + math.max(machines_height, items_height)
|
|
end
|
|
return total_height
|
|
end
|
|
|
|
local function determine_column_counts(lines, available_columns)
|
|
local column_counts = {Ingredient = 1, Product = 1, Byproduct = 0} -- ordered by priority
|
|
available_columns = available_columns - 2 -- two buttons are already assigned
|
|
|
|
local previous_height, increment = math.huge, 1
|
|
while available_columns > 0 do
|
|
local table_heights, minimal_height = {}, math.huge
|
|
|
|
for column, count in pairs(column_counts) do
|
|
local potential_column_counts = fancytable.shallow_copy(column_counts)
|
|
potential_column_counts[column] = count + increment
|
|
local new_height = determine_table_height(lines, potential_column_counts)
|
|
table_heights[column] = new_height
|
|
minimal_height = math.min(minimal_height, new_height)
|
|
end
|
|
|
|
-- If increasing any column by 1 doesn't change the height, try incrementing by more
|
|
-- until height is decreased, or no columns are available anymore
|
|
if not (minimal_height < previous_height) and increment < available_columns then
|
|
increment = increment + 1
|
|
else
|
|
for column, height in pairs(table_heights) do
|
|
if available_columns > 0 and height == minimal_height then
|
|
column_counts[column] = column_counts[column] + 1
|
|
available_columns = available_columns - 1
|
|
break
|
|
end
|
|
end
|
|
|
|
previous_height, increment = minimal_height, 1 -- reset these
|
|
end
|
|
end
|
|
|
|
return column_counts
|
|
end
|
|
|
|
|
|
local function add_checkmark_button(parent_flow, line, relevant_line)
|
|
parent_flow.add{type="checkbox", state=relevant_line.done, mouse_button_filter={"left"},
|
|
tags={mod="fp", on_gui_checked_state_changed="checkmark_compact_line", line_id=line.id}}
|
|
end
|
|
|
|
local function add_recipe_button(parent_flow, line, relevant_line, metadata)
|
|
local recipe_proto = relevant_line.recipe.proto
|
|
local style = (line.subfloor ~= nil) and "flib_slot_button_blue_small" or "flib_slot_button_default_small"
|
|
style = (relevant_line.done) and "flib_slot_button_grayscale_small" or style
|
|
local tooltip = (line.subfloor == nil) and {"fp.tt_title", recipe_proto.localised_name}
|
|
or {"", {"fp.tt_title", recipe_proto.localised_name}, metadata.recipe_tutorial_tt}
|
|
|
|
parent_flow.add{type="sprite-button", tags={mod="fp", on_gui_click="act_on_compact_recipe", line_id=line.id},
|
|
sprite=recipe_proto.sprite, tooltip=tooltip, style=style, mouse_button_filter={"left-and-right"}}
|
|
end
|
|
|
|
local function add_modules_flow(parent_flow, parent_type, line, metadata)
|
|
for _, module in ipairs(ModuleSet.get_in_order(line[parent_type].module_set)) do
|
|
local number_line = {"", "\n", module.amount, " ", {"fp.pl_module", module.amount}}
|
|
local tooltip = {"", {"fp.tt_title", module.proto.localised_name}, number_line, metadata.module_tutorial_tt}
|
|
local style = (line.done) and "flib_slot_button_grayscale_small" or "flib_slot_button_default_small"
|
|
|
|
parent_flow.add{type="sprite-button", sprite=module.proto.sprite, tooltip=tooltip,
|
|
tags={mod="fp", on_gui_click="act_on_compact_module", line_id=line.id, module_id=module.id,
|
|
parent_type=parent_type}, number=module.amount, style=style, mouse_button_filter={"left-and-right"}}
|
|
end
|
|
end
|
|
|
|
local function add_machine_flow(parent_flow, line, metadata)
|
|
if line.subfloor == nil then
|
|
local machine_flow = parent_flow.add{type="flow", direction="horizontal"}
|
|
local machine_proto = line.machine.proto
|
|
|
|
local count, tooltip_line = util.format.machine_count(line.machine.count, (line.production_ratio > 0), true)
|
|
local tooltip = {"", {"fp.tt_title", machine_proto.localised_name}, "\n", tooltip_line,
|
|
metadata.machine_tutorial_tt}
|
|
local style = (line.done) and "flib_slot_button_grayscale_small" or "flib_slot_button_default_small"
|
|
|
|
machine_flow.add{type="sprite-button", sprite=machine_proto.sprite, number=count,
|
|
tooltip=tooltip, tags={mod="fp", on_gui_click="act_on_compact_machine", type="machine", line_id=line.id},
|
|
style=style, mouse_button_filter={"left-and-right"}}
|
|
|
|
add_modules_flow(machine_flow, "machine", line, metadata)
|
|
end
|
|
end
|
|
|
|
local function add_beacon_flow(parent_flow, line, metadata)
|
|
if line.subfloor == nil and line.beacon ~= nil then
|
|
local beacon_flow = parent_flow.add{type="flow", direction="horizontal"}
|
|
local beacon_proto = line.beacon.proto
|
|
|
|
local plural_parameter = (line.beacon.amount == 1) and 1 or 2 -- needed because the amount can be decimal
|
|
local number_line = {"", "\n", line.beacon.amount, " ", {"fp.pl_beacon", plural_parameter}}
|
|
local tooltip = {"", {"fp.tt_title", beacon_proto.localised_name}, number_line, metadata.beacon_tutorial_tt}
|
|
local style = (line.done) and "flib_slot_button_grayscale_small" or "flib_slot_button_default_small"
|
|
|
|
beacon_flow.add{type="sprite-button", sprite=beacon_proto.sprite, number=line.beacon.amount,
|
|
tooltip=tooltip, tags={mod="fp", on_gui_click="act_on_compact_beacon", type="beacon", line_id=line.id},
|
|
style=style, mouse_button_filter={"left-and-right"}}
|
|
|
|
add_modules_flow(beacon_flow, "beacon", line, metadata)
|
|
end
|
|
end
|
|
|
|
|
|
local function add_item_flow(line, relevant_line, item_class, button_color, metadata, item_buttons)
|
|
local column_count = metadata.column_counts[item_class]
|
|
if column_count == 0 then metadata.parent.add{type="empty-widget"}; return end
|
|
local item_table = metadata.parent.add{type="table", column_count=column_count}
|
|
|
|
for _, item in ipairs(Line.get_in_order(line, item_class)) do
|
|
local proto, type = item.proto, item.proto.type
|
|
-- items/s/machine does not make sense for lines with subfloors, show items/s instead
|
|
local machine_count = (not line.subfloor) and line.machine.count or nil
|
|
local amount, number_tooltip = view_state.process_item(metadata.view_state_metadata, item, nil, machine_count)
|
|
if amount == -1 then goto skip_item end -- an amount of -1 means it was below the margin of error
|
|
|
|
local number_line = (number_tooltip) and {"", "\n", number_tooltip} or ""
|
|
local tooltip = {"", {"fp.tt_title", proto.localised_name}, number_line, metadata.item_tutorial_tt}
|
|
local style, enabled = "flib_slot_button_" .. button_color .. "_small", true
|
|
if relevant_line.done then style = "flib_slot_button_grayscale_small" end
|
|
|
|
if type == "entity" then
|
|
style = (relevant_line.done) and "flib_slot_button_transparent_grayscale_small"
|
|
or "flib_slot_button_transparent_small"
|
|
enabled = false
|
|
tooltip = {"", {"fp.tt_title_with_note", proto.localised_name, {"fp.raw_ore"}}, number_line}
|
|
end
|
|
|
|
local button = item_table.add{type="sprite-button", sprite=proto.sprite, number=amount, tooltip=tooltip,
|
|
tags={mod="fp", on_gui_click="act_on_compact_item", on_gui_hover="hover_compact_item",
|
|
on_gui_leave="leave_compact_item", line_id=line.id, class=item.class, item_id=item.id},
|
|
style=style, enabled=enabled, mouse_button_filter={"left-and-right"}}
|
|
|
|
button.raise_hover_events = true
|
|
item_buttons[type] = item_buttons[type] or {}
|
|
item_buttons[type][proto.name] = item_buttons[type][proto.name] or {}
|
|
table.insert(item_buttons[type][proto.name], {button=button, proper_style=style})
|
|
|
|
::skip_item::
|
|
end
|
|
|
|
if item_class == "Ingredient" and not line.subfloor and line.machine.fuel then
|
|
local fuel, machine_count = line.machine.fuel, line.machine.count
|
|
local amount, number_tooltip = view_state.process_item(metadata.view_state_metadata, fuel, nil, machine_count)
|
|
if amount == -1 then goto skip_fuel end -- an amount of -1 means it was below the margin of error
|
|
|
|
local name_line = {"fp.tt_title_with_note", fuel.proto.localised_name, {"fp.pl_fuel", 1}}
|
|
local number_line = (number_tooltip) and {"", "\n", number_tooltip} or ""
|
|
local tooltip = {"", name_line, number_line, metadata.item_tutorial_tt}
|
|
local style = (relevant_line.done) and "flib_slot_button_grayscale_small" or "flib_slot_button_cyan_small"
|
|
|
|
item_table.add{type="sprite-button", sprite=fuel.proto.sprite, style=style, number=amount,
|
|
tags={mod="fp", on_gui_click="act_on_compact_item", line_id=line.id, class="Fuel"},
|
|
tooltip=tooltip, mouse_button_filter={"left-and-right"}}
|
|
|
|
::skip_fuel::
|
|
end
|
|
end
|
|
|
|
|
|
local function refresh_compact_subfactory(player)
|
|
local player_table = util.globals.player_table(player)
|
|
local compact_elements = player_table.ui_state.compact_elements
|
|
local context = player_table.ui_state.context
|
|
local subfactory = context.subfactory
|
|
if not subfactory or not subfactory.valid then return end
|
|
|
|
local current_level = subfactory.selected_floor.level
|
|
local lines = Floor.get_in_order(context.floor, "Line")
|
|
|
|
util.raise.refresh(player, "view_state", compact_elements.view_state_table)
|
|
|
|
local attach_subfactory_products = player_table.preferences.attach_subfactory_products
|
|
compact_elements.name_label.caption = Subfactory.tostring(subfactory, attach_subfactory_products, true)
|
|
|
|
compact_elements.level_label.caption = {"fp.bold_label", {"", "- ", {"fp.level"}, " ", current_level}}
|
|
compact_elements.floor_up_button.enabled = (current_level > 1)
|
|
compact_elements.floor_top_button.enabled = (current_level > 1)
|
|
|
|
local production_table = compact_elements.production_table
|
|
production_table.clear()
|
|
|
|
-- Available columns for items only, as recipe and machines can't be 'compressed'
|
|
local frame_width = compact_elements.compact_frame.style.maximal_width
|
|
local available_columns = determine_available_columns(lines, frame_width)
|
|
if available_columns < 2 then available_columns = 2 end -- fix for too many modules or too high of a GUI scale
|
|
local column_counts = determine_column_counts(lines, available_columns)
|
|
|
|
local metadata = {
|
|
parent = production_table,
|
|
column_counts = column_counts,
|
|
view_state_metadata = view_state.generate_metadata(player, subfactory)
|
|
}
|
|
|
|
compact_elements.item_buttons = {} -- (re)set the item_buttons table
|
|
local item_buttons = compact_elements.item_buttons
|
|
|
|
if util.globals.preferences(player).tutorial_mode then
|
|
util.actions.tutorial_tooltip_list(metadata, player, {
|
|
recipe_tutorial_tt = "act_on_compact_recipe",
|
|
module_tutorial_tt = "act_on_compact_module",
|
|
machine_tutorial_tt = "act_on_compact_machine",
|
|
beacon_tutorial_tt = "act_on_compact_beacon",
|
|
item_tutorial_tt = "act_on_compact_item",
|
|
})
|
|
end
|
|
|
|
for _, line in ipairs(lines) do -- build the individual lines
|
|
local relevant_line = (line.subfloor) and line.subfloor.defining_line or line
|
|
if not relevant_line.active then goto skip_line end
|
|
|
|
-- Recipe and Checkmark
|
|
local recipe_flow = production_table.add{type="flow", direction="horizontal"}
|
|
recipe_flow.style.vertical_align = "center"
|
|
add_checkmark_button(recipe_flow, line, relevant_line)
|
|
add_recipe_button(recipe_flow, line, relevant_line, metadata)
|
|
|
|
-- Machine and Beacon
|
|
local machines_flow = production_table.add{type="flow", direction="vertical"}
|
|
add_machine_flow(machines_flow, line, metadata)
|
|
add_beacon_flow(machines_flow, line, metadata)
|
|
|
|
-- Products, Byproducts and Ingredients
|
|
add_item_flow(line, relevant_line, "Product", "default", metadata, item_buttons)
|
|
add_item_flow(line, relevant_line, "Byproduct", "red", metadata, item_buttons)
|
|
add_item_flow(line, relevant_line, "Ingredient", "green", metadata, item_buttons)
|
|
|
|
production_table.add{type="empty-widget", style="flib_horizontal_pusher"}
|
|
|
|
::skip_line::
|
|
end
|
|
end
|
|
|
|
local function build_compact_subfactory(player)
|
|
local ui_state = util.globals.ui_state(player)
|
|
local compact_elements = ui_state.compact_elements
|
|
|
|
-- Content frame
|
|
local content_frame = compact_elements.compact_frame.add{type="frame", direction="vertical",
|
|
style="inside_deep_frame"}
|
|
content_frame.style.vertically_stretchable = true
|
|
|
|
local subheader = content_frame.add{type="frame", direction="vertical", style="subheader_frame"}
|
|
subheader.style.maximal_height = 100 -- large value to nullify maximal_height
|
|
|
|
-- Flow view state
|
|
local flow_view_state = subheader.add{type="flow", direction="horizontal"}
|
|
flow_view_state.style.padding = {4, 4, 0, 0}
|
|
flow_view_state.add{type="empty-widget", style="flib_horizontal_pusher"}
|
|
|
|
view_state.rebuild_state(player) -- initializes the view_state
|
|
util.raise.build(player, "view_state", flow_view_state)
|
|
compact_elements["view_state_table"] = flow_view_state["table_view_state"]
|
|
|
|
subheader.add{type="line", direction="horizontal"}
|
|
|
|
-- Flow navigation
|
|
local flow_navigation = subheader.add{type="flow", direction="horizontal"}
|
|
flow_navigation.style.vertical_align = "center"
|
|
flow_navigation.style.margin = {4, 8}
|
|
|
|
local label_name = flow_navigation.add{type="label"}
|
|
label_name.style.font = "heading-2"
|
|
label_name.style.maximal_width = 260
|
|
compact_elements["name_label"] = label_name
|
|
|
|
local label_level = flow_navigation.add{type="label"}
|
|
label_level.style.margin = {0, 6, 0, 6}
|
|
compact_elements["level_label"] = label_level
|
|
|
|
local button_floor_up = flow_navigation.add{type="sprite-button", sprite="fp_sprite_arrow_line_up",
|
|
tooltip={"fp.floor_up_tt"}, tags={mod="fp", on_gui_click="change_compact_floor", destination="up"},
|
|
style="fp_sprite-button_rounded_mini", mouse_button_filter={"left"}}
|
|
compact_elements["floor_up_button"] = button_floor_up
|
|
|
|
local button_floor_top = flow_navigation.add{type="sprite-button", sprite="fp_sprite_arrow_line_bar_up",
|
|
tooltip={"fp.floor_top_tt"}, tags={mod="fp", on_gui_click="change_compact_floor", destination="top"},
|
|
style="fp_sprite-button_rounded_mini", mouse_button_filter={"left"}}
|
|
compact_elements["floor_top_button"] = button_floor_top
|
|
|
|
-- Production table
|
|
local scroll_pane_production = content_frame.add{type="scroll-pane", direction="vertical",
|
|
style="flib_naked_scroll_pane_no_padding"}
|
|
scroll_pane_production.style.horizontally_stretchable = true
|
|
|
|
local table_production = scroll_pane_production.add{type="table", column_count=6, style="fp_table_production"}
|
|
table_production.vertical_centering = false
|
|
table_production.style.horizontal_spacing = 12
|
|
table_production.style.vertical_spacing = 8
|
|
table_production.style.padding = {4, 8}
|
|
compact_elements["production_table"] = table_production
|
|
|
|
refresh_compact_subfactory(player)
|
|
end
|
|
|
|
|
|
local function handle_recipe_click(player, tags, action)
|
|
local context = util.globals.context(player)
|
|
local line = Floor.get(context.floor, "Line", tags.line_id)
|
|
local relevant_line = (line.subfloor) and line.subfloor.defining_line or line
|
|
local recipe = relevant_line.recipe
|
|
|
|
if action == "open_subfloor" then
|
|
if line.subfloor then
|
|
util.context.set_floor(player, line.subfloor)
|
|
refresh_compact_subfactory(player)
|
|
end
|
|
|
|
elseif action == "recipebook" then
|
|
util.open_in_recipebook(player, "recipe", recipe.proto.name)
|
|
end
|
|
end
|
|
|
|
local function handle_module_click(player, tags, action)
|
|
local context = util.globals.context(player)
|
|
local line = Floor.get(context.floor, "Line", tags.line_id)
|
|
-- I don't need to care about relevant lines here because this only gets called on lines without subfloor
|
|
local parent_entity = line[tags.parent_type]
|
|
local module = ModuleSet.get(parent_entity.module_set, tags.module_id)
|
|
|
|
if action == "recipebook" then
|
|
util.open_in_recipebook(player, "item", module.proto.name)
|
|
end
|
|
end
|
|
|
|
local function handle_machine_click(player, tags, action)
|
|
local context = util.globals.context(player)
|
|
local line = Floor.get(context.floor, "Line", tags.line_id)
|
|
-- I don't need to care about relevant lines here because this only gets called on lines without subfloor
|
|
|
|
if action == "put_into_cursor" then
|
|
util.cursor.set_entity(player, line, line.machine)
|
|
|
|
elseif action == "recipebook" then
|
|
util.open_in_recipebook(player, "entity", line.machine.proto.name)
|
|
end
|
|
end
|
|
|
|
local function handle_beacon_click(player, tags, action)
|
|
local context = util.globals.context(player)
|
|
local line = Floor.get(context.floor, "Line", tags.line_id)
|
|
-- I don't need to care about relevant lines here because this only gets called on lines without subfloor
|
|
|
|
if action == "put_into_cursor" then
|
|
util.cursor.set_entity(player, line, line.beacon)
|
|
|
|
elseif action == "recipebook" then
|
|
util.open_in_recipebook(player, "entity", line.beacon.proto.name)
|
|
end
|
|
end
|
|
|
|
local function handle_item_click(player, tags, action)
|
|
local context = util.globals.context(player)
|
|
local line = Floor.get(context.floor, "Line", tags.line_id)
|
|
local item = (tags.class == "Fuel") and line.machine.fuel or Line.get(line, tags.class, tags.item_id)
|
|
|
|
if action == "put_into_cursor" then
|
|
util.cursor.add_to_item_combinator(player, item.proto, item.amount)
|
|
|
|
elseif action == "recipebook" then
|
|
util.open_in_recipebook(player, item.proto.type, item.proto.name)
|
|
end
|
|
end
|
|
|
|
local function handle_hover_change(player, tags, event)
|
|
local ui_state = util.globals.ui_state(player)
|
|
local line = Floor.get(ui_state.context.floor, "Line", tags.line_id)
|
|
local proto = Line.get(line, tags.class, tags.item_id).proto
|
|
|
|
local relevant_buttons = ui_state.compact_elements.item_buttons[proto.type][proto.name]
|
|
for _, button_data in pairs(relevant_buttons) do
|
|
button_data.button.style = (event.name == defines.events.on_gui_hover)
|
|
and "flib_slot_button_pink_small" or button_data.proper_style
|
|
end
|
|
end
|
|
|
|
|
|
-- ** EVENTS **
|
|
local subfactory_listeners = {}
|
|
|
|
subfactory_listeners.gui = {
|
|
on_gui_click = {
|
|
{
|
|
name = "change_compact_floor",
|
|
handler = (function(player, tags, _)
|
|
local floor_changed = util.context.change_floor(player, tags.destination)
|
|
if floor_changed then refresh_compact_subfactory(player) end
|
|
end)
|
|
},
|
|
{
|
|
name = "act_on_compact_recipe",
|
|
modifier_actions = {
|
|
open_subfloor = {"left"},
|
|
recipebook = {"alt-right", {recipebook=true}}
|
|
},
|
|
handler = handle_recipe_click
|
|
},
|
|
{
|
|
name = "act_on_compact_module",
|
|
modifier_actions = {
|
|
recipebook = {"alt-right", {recipebook=true}}
|
|
},
|
|
handler = handle_module_click
|
|
},
|
|
{
|
|
name = "act_on_compact_machine",
|
|
modifier_actions = {
|
|
put_into_cursor = {"left"},
|
|
recipebook = {"alt-right", {recipebook=true}}
|
|
},
|
|
handler = handle_machine_click
|
|
},
|
|
{
|
|
name = "act_on_compact_beacon",
|
|
modifier_actions = {
|
|
put_into_cursor = {"left"},
|
|
recipebook = {"alt-right", {recipebook=true}}
|
|
},
|
|
handler = handle_beacon_click
|
|
},
|
|
{
|
|
name = "act_on_compact_item",
|
|
modifier_actions = {
|
|
put_into_cursor = {"left"},
|
|
recipebook = {"alt-right", {recipebook=true}}
|
|
},
|
|
handler = handle_item_click
|
|
}
|
|
},
|
|
on_gui_checked_state_changed = {
|
|
{
|
|
name = "checkmark_compact_line",
|
|
handler = (function(player, tags, _)
|
|
local line = Floor.get(util.globals.context(player).floor, "Line", tags.line_id)
|
|
local relevant_line = (line.subfloor) and line.subfloor.defining_line or line
|
|
relevant_line.done = not relevant_line.done
|
|
refresh_compact_subfactory(player)
|
|
end)
|
|
}
|
|
},
|
|
on_gui_hover = {
|
|
{
|
|
name = "hover_compact_item",
|
|
handler = handle_hover_change
|
|
}
|
|
},
|
|
on_gui_leave = {
|
|
{
|
|
name = "leave_compact_item",
|
|
handler = handle_hover_change
|
|
}
|
|
}
|
|
}
|
|
|
|
subfactory_listeners.misc = {
|
|
build_gui_element = (function(player, event)
|
|
if event.trigger == "compact_subfactory" then
|
|
build_compact_subfactory(player)
|
|
end
|
|
end),
|
|
refresh_gui_element = (function(player, event)
|
|
if event.trigger == "compact_subfactory" then
|
|
refresh_compact_subfactory(player)
|
|
end
|
|
end)
|
|
}
|
|
|
|
|
|
|
|
-- The frame surrounding the main part of the compact subfactory
|
|
local frame_dimensions = {width = 0.25, height = 0.8} -- as a percentage of the screen
|
|
local frame_location = {x = 10, y = 63} -- absolute, relative to 1080p with scale 1
|
|
|
|
-- ** LOCAL UTIL **
|
|
-- Set frame dimensions in a relative way, taking player resolution and scaling into account
|
|
local function set_compact_frame_dimensions(player, frame)
|
|
local resolution, scale = player.display_resolution, player.display_scale
|
|
local actual_resolution = {width=math.ceil(resolution.width / scale), height=math.ceil(resolution.height / scale)}
|
|
frame.style.width = actual_resolution.width * frame_dimensions.width
|
|
frame.style.maximal_height = actual_resolution.height * frame_dimensions.height
|
|
end
|
|
|
|
local function set_compact_frame_location(player, frame)
|
|
local scale = player.display_scale
|
|
frame.location = {frame_location.x * scale, frame_location.y * scale}
|
|
end
|
|
|
|
local function rebuild_compact_dialog(player, default_visibility)
|
|
local ui_state = util.globals.ui_state(player)
|
|
local compact_elements = ui_state.compact_elements
|
|
|
|
local interface_visible = default_visibility
|
|
local compact_frame = compact_elements.compact_frame
|
|
-- Delete the existing interface if there is one
|
|
if compact_frame ~= nil then
|
|
if compact_frame.valid then
|
|
interface_visible = compact_frame.visible
|
|
compact_frame.destroy()
|
|
end
|
|
|
|
ui_state.compact_elements = {} -- reset all compact element references
|
|
compact_elements = ui_state.compact_elements
|
|
end
|
|
|
|
local frame_compact_dialog = player.gui.screen.add{type="frame", direction="vertical",
|
|
visible=interface_visible, name="fp_frame_compact_dialog"}
|
|
set_compact_frame_location(player, frame_compact_dialog)
|
|
set_compact_frame_dimensions(player, frame_compact_dialog)
|
|
compact_elements["compact_frame"] = frame_compact_dialog
|
|
|
|
-- Title bar
|
|
local flow_title_bar = frame_compact_dialog.add{type="flow", direction="horizontal",
|
|
tags={mod="fp", on_gui_click="place_compact_dialog"}}
|
|
flow_title_bar.style.horizontal_spacing = 8
|
|
flow_title_bar.drag_target = frame_compact_dialog
|
|
|
|
flow_title_bar.add{type="label", caption={"mod-name.factoryplanner"}, style="frame_title",
|
|
ignored_by_interaction=true}
|
|
flow_title_bar.add{type="empty-widget", style="flib_titlebar_drag_handle",
|
|
ignored_by_interaction=true}
|
|
|
|
local button_switch = flow_title_bar.add{type="sprite-button", style="frame_action_button",
|
|
tags={mod="fp", on_gui_click="switch_to_main_view"}, tooltip={"fp.switch_to_main_view"},
|
|
sprite="fp_sprite_arrow_right_light", hovered_sprite="fp_sprite_arrow_right_dark",
|
|
clicked_sprite="fp_sprite_arrow_right_dark", mouse_button_filter={"left"}}
|
|
button_switch.style.padding = 2
|
|
|
|
local button_close = flow_title_bar.add{type="sprite-button", tags={mod="fp", on_gui_click="close_compact_dialog"},
|
|
sprite="utility/close_white", hovered_sprite="utility/close_black", clicked_sprite="utility/close_black",
|
|
tooltip={"fp.close_interface"}, style="frame_action_button", mouse_button_filter={"left"}}
|
|
button_close.style.padding = 1
|
|
|
|
util.raise.build(player, "compact_subfactory", nil)
|
|
|
|
return frame_compact_dialog
|
|
end
|
|
|
|
|
|
-- ** TOP LEVEL **
|
|
compact_dialog = {}
|
|
|
|
function compact_dialog.toggle(player)
|
|
local ui_state = util.globals.ui_state(player)
|
|
local frame_compact_dialog = ui_state.compact_elements.compact_frame
|
|
-- Doesn't set player.opened so other GUIs like the inventory can be opened when building
|
|
|
|
if frame_compact_dialog == nil or not frame_compact_dialog.valid then
|
|
rebuild_compact_dialog(player, true) -- refreshes on its own
|
|
else
|
|
local new_dialog_visibility = not frame_compact_dialog.visible
|
|
frame_compact_dialog.visible = new_dialog_visibility
|
|
|
|
if new_dialog_visibility then refresh_compact_subfactory(player) end
|
|
end
|
|
end
|
|
|
|
function compact_dialog.is_in_focus(player)
|
|
local frame_compact_dialog = util.globals.ui_state(player).compact_elements.compact_frame
|
|
return (frame_compact_dialog ~= nil and frame_compact_dialog.valid and frame_compact_dialog.visible)
|
|
end
|
|
|
|
|
|
-- ** EVENTS **
|
|
local dialog_listeners = {}
|
|
|
|
dialog_listeners.gui = {
|
|
on_gui_click = {
|
|
{
|
|
name = "switch_to_main_view",
|
|
handler = (function(player, _, _)
|
|
util.globals.flags(player).compact_view = false
|
|
compact_dialog.toggle(player)
|
|
|
|
main_dialog.toggle(player)
|
|
util.raise.refresh(player, "production", nil)
|
|
end)
|
|
},
|
|
{
|
|
name = "close_compact_dialog",
|
|
handler = (function(player, _, _)
|
|
compact_dialog.toggle(player)
|
|
end)
|
|
},
|
|
{
|
|
name = "place_compact_dialog",
|
|
handler = (function(player, _, event)
|
|
if event.button == defines.mouse_button_type.middle then
|
|
local ui_state = util.globals.ui_state(player)
|
|
local frame_compact_dialog = ui_state.compact_elements.compact_frame
|
|
set_compact_frame_location(player, frame_compact_dialog)
|
|
end
|
|
end)
|
|
}
|
|
}
|
|
}
|
|
|
|
dialog_listeners.misc = {
|
|
on_player_display_resolution_changed = (function(player, _)
|
|
rebuild_compact_dialog(player, false)
|
|
end),
|
|
|
|
on_player_display_scale_changed = (function(player, _)
|
|
rebuild_compact_dialog(player, false)
|
|
end),
|
|
|
|
on_lua_shortcut = (function(player, event)
|
|
if event.prototype_name == "fp_open_interface" and util.globals.flags(player).compact_view then
|
|
compact_dialog.toggle(player)
|
|
end
|
|
end),
|
|
|
|
fp_toggle_interface = (function(player, _)
|
|
if util.globals.flags(player).compact_view then compact_dialog.toggle(player) end
|
|
end)
|
|
}
|
|
|
|
return { subfactory_listeners, dialog_listeners }
|