--- @class Gui local Gui = require("modules/exp_gui") --- @class Gui.elements local Elements = {} Gui.elements = Elements --- @class Gui.elements.aligned_flow.opts --- @field horizontal_align ("left" | "center" | "right")? --- @field vertical_align ("top" | "center" | "bottom")? --- A flow which aligns its content as specified --- @class Gui.elements.aligned_flow: ExpElement --- @overload fun(parent: LuaGuiElement, opts: Gui.elements.aligned_flow.opts?): LuaGuiElement Elements.aligned_flow = Gui.define("aligned_flow") :draw{ type = "flow", name = Gui.from_argument("name"), } :style(function(def, element, parent, opts) opts = opts or {} --- @cast opts Gui.elements.aligned_flow.opts local vertical_align = opts.vertical_align or "center" local horizontal_align = opts.horizontal_align or "right" return { padding = { 1, 2 }, vertical_align = vertical_align, horizontal_align = horizontal_align, vertically_stretchable = vertical_align ~= "center", horizontally_stretchable = horizontal_align ~= "center", } end) --[[ @as any ]] --- A solid horizontal white bar element --- @class Gui.elements.bar: ExpElement --- @overload fun(parent: LuaGuiElement, width: number?): LuaGuiElement Elements.bar = Gui.define("bar") :draw{ type = "progressbar", value = 1, } :style(function(def, element, parent, width) --- @cast width number? local style = element.style style.color = { r = 255, g = 255, b = 255 } style.height = 4 if width then style.width = width else style.horizontally_stretchable = true end end) --[[ @as any ]] --- A label which is centered --- @class Gui.elements.centered_label: ExpElement --- @overload fun(parent: LuaGuiElement, width: number, caption: LocalisedString, tooltip: LocalisedString?): LuaGuiElement Elements.centered_label = Gui.define("centered_label") :draw{ type = "label", caption = Gui.from_argument(2), tooltip = Gui.from_argument(3), } :style{ horizontal_align = "center", single_line = false, width = Gui.from_argument(1), } --[[ @as any ]] --- A label which has two white bars on either side of it --- @class Gui.elements.title_label: ExpElement --- @overload fun(parent: LuaGuiElement, width: number, caption: LocalisedString, tooltip: LocalisedString?): LuaGuiElement Elements.title_label = Gui.define("title_label") :draw(function(def, parent, width, caption, tooltip) --- @cast width number --- @cast caption LocalisedString --- @cast tooltip LocalisedString? local flow = parent.add{ type = "flow" } flow.style.vertical_align = "center" Elements.bar(flow, width) local label = flow.add{ type = "label", style = "frame_title", caption = caption, tooltip = tooltip, } Elements.bar(flow) return label end) --[[ @as any ]] --- A fixed size vertical scroll pane --- @class Gui.elements.scroll_pane: ExpElement --- @overload fun(parent: LuaGuiElement, maximal_height: number, name: string?): LuaGuiElement Elements.scroll_pane = Gui.define("scroll_pane") :draw{ type = "scroll-pane", name = Gui.from_argument(2), direction = "vertical", horizontal_scroll_policy = "never", vertical_scroll_policy = "auto", style = "scroll_pane_under_subheader", } :style{ padding = { 1, 3 }, maximal_height = Gui.from_argument(1), horizontally_stretchable = true, } --[[ @as any ]] --- A fixed size vertical scroll pane containing a table --- @class Gui.elements.scroll_table: ExpElement --- @overload fun(parent: LuaGuiElement, maximal_height: number, column_count: number, scroll_name: string?): LuaGuiElement Elements.scroll_table = Gui.define("scroll_table") :draw(function(def, parent, maximal_height, column_count, scroll_name) --- @cast maximal_height number --- @cast column_count number --- @cast scroll_name string? local scroll_pane = Elements.scroll_pane(parent, maximal_height, scroll_name) return scroll_pane.add{ type = "table", name = "table", column_count = column_count, } end) :style{ padding = { 3, 2 }, cell_padding = 1, vertical_align = "center", horizontally_stretchable = true, } --[[ @as any ]] --- A container frame --- @class Gui.elements.container: ExpElement --- @overload fun(parent: LuaGuiElement, minimal_width: number?, name: string?): LuaGuiElement Elements.container = Gui.define("container") :draw(function(def, parent, minimal_width, name) --- @cast minimal_width number? --- @cast name string? local container = parent.add{ type = "frame", name = name, } container.style.padding = 2 return container.add{ type = "frame", name = "frame", direction = "vertical", style = "inside_shallow_frame_packed", } end) :style{ vertically_stretchable = false, horizontally_stretchable = false, minimal_width = Gui.from_argument(1), } --[[ @as any ]] --- Get the root element of a container --- @param container LuaGuiElement --- @return LuaGuiElement function Elements.container.get_root_element(container) return container.parent end --- A frame within a container --- @class Gui.elements.subframe_base: ExpElement --- @overload fun(parent: LuaGuiElement, style: string, name: string?): LuaGuiElement Elements.subframe_base = Gui.define("container_subframe") :draw{ type = "frame", name = Gui.from_argument(2), style = Gui.from_argument(1), } :style{ height = 0, minimal_height = 36, padding = { 3, 6, 0, 6 }, use_header_filler = false, horizontally_stretchable = true, } --[[ @as any ]] --- @class Gui.elements.header.opts --- @field name string? --- @field caption LocalisedString? --- @field tooltip LocalisedString? --- A header frame within a container --- @class Gui.elements.header: ExpElement --- @field label LuaGuiElement --- @overload fun(parent: LuaGuiElement, opts: Gui.elements.header.opts?): LuaGuiElement Elements.header = Gui.define("container_header") :draw(function(def, parent, opts) opts = opts or {} --- @cast opts Gui.elements.header.opts local subframe = Elements.subframe_base(parent, "subheader_frame", opts.name) if opts.caption then subframe.add{ type = "label", name = "label", caption = opts.caption, tooltip = opts.tooltip, style = "frame_title", } end subframe.add{ type = "empty-widget" }.style.horizontally_stretchable = true return subframe end) --[[ @as any ]] --- @class Gui.elements.footer.opts --- @field name string? --- @field caption LocalisedString? --- @field tooltip LocalisedString? --- A footer frame within a container --- @class Gui.elements.footer: ExpElement --- @field label LuaGuiElement --- @overload fun(parent: LuaGuiElement, opts: Gui.elements.footer.opts?): LuaGuiElement Elements.footer = Gui.define("container_footer") :draw(function(def, parent, opts) opts = opts or {} --- @cast opts Gui.elements.footer.opts local subframe = Elements.subframe_base(parent, "subfooter_frame", opts.name) if opts.caption then subframe.add{ type = "label", name = "label", caption = opts.caption, tooltip = opts.tooltip, style = "frame_title", } end subframe.add{ type = "empty-widget" }.style.horizontally_stretchable = true return subframe end) --[[ @as any ]] --- A button used to destroy its target when clicked, intended for screen frames --- @class Gui.elements.screen_frame_close: ExpElement --- @field data table --- @overload fun(parent: LuaGuiElement, target: LuaGuiElement): LuaGuiElement Elements.screen_frame_close = Gui.define("screen_frame_close") :draw{ type = "sprite-button", style = "frame_action_button", sprite = "utility/close", } :element_data( Gui.from_argument(1) ) :on_click(function(def, player, element, event) --- @cast def Gui.elements.screen_frame_close Gui.destroy_if_valid(def.data[element]) end) --[[ @as any ]] --- A draggable frame with close button and button flow --- @class Gui.elements.screen_frame: ExpElement --- @field data table --- @overload fun(parent: LuaGuiElement, caption: LocalisedString?, button_flow: boolean?): LuaGuiElement Elements.screen_frame = Gui.define("screen_frame") :draw(function(def, parent, caption, button_flow) local container = parent.add{ type = "frame", direction = "vertical", } container.style.padding = 2 local header = container.add{ type = "flow", } if caption then local label = header.add{ type = "label", caption = caption, style = "frame_title" } label.style.top_margin = -3 label.style.bottom_padding = 3 end local filler = header.add{ type = "empty-widget", style = "draggable_space_header", } filler.drag_target = container local filler_style = filler.style filler_style.horizontally_stretchable = true filler_style.vertically_stretchable = true filler_style.left_margin = caption and 4 or 0 filler_style.natural_height = 24 filler_style.height = 24 if button_flow then local _button_flow = header.add{ type = "flow" } def.data[container] = _button_flow _button_flow.style.padding = 0 end Elements.screen_frame_close(header, container) return container.add{ type = "frame", direction = "vertical", style = "inside_shallow_frame_packed", } end) --[[ @as any ]] --- Get the button flow for a screen frame --- @param screen_frame LuaGuiElement --- @return LuaGuiElement function Elements.screen_frame.get_button_flow(screen_frame) return assert(Elements.screen_frame.data[screen_frame.parent], "Screen frame has no button flow") end --- Get the root element of a screen frame --- @param screen_frame LuaGuiElement --- @return LuaGuiElement function Elements.screen_frame.get_root_element(screen_frame) return screen_frame.parent end return Elements