gui-beta module

GUI structuring tools and event handling (beta).

This new GUI module makes use of a new feature in Factorio 1.1: GUI element tags. This significantly simplifies the logic around event handling. Due to the backward-incompatible nature of the changes, this new module was created instead of upgrading the old one. This module will replace the current non-beta module when Factorio 1.2 releases.

See also

Usage

local gui = require("__flib__.gui-beta")

Functions

hook_events(callback) Provide a callback to be run for GUI events.
read_action(event_data) Retrieve the action message from a GUI element’s tags.
build(parent, structures) Build a GUI based on the given structure(s).
update(elem, updates) Update an existing GUI based on a given structure.
get_tags(elem) Retrieve a GUI element’s tags.
set_tags(elem, tags) Set (override) a GUI element’s tags.
delete_tags(elem) Delete a GUI element’s tags.
update_tags(elem, updates) Perform a shallow merge on a GUI element’s tags.

Concepts

GuiBuildStructure A series of nested tables used to build a GUI.
GuiUpdateStructure A series of nested tables used to update a GUI.
GuiElementActions A mapping of GUI event name –> action message.
TabAndContent A table representing a tab <–> content pair.

Functions

# hook_events(callback)

Provide a callback to be run for GUI events.

Parameters: See also: Usage:
gui.hook_events(function(e)
  local msg = gui.read_action(e)
  if msg then
    -- read the action to determine what to do
  end
end)
# read_action(event_data)

Retrieve the action message from a GUI element’s tags.

Parameters:
  • event_data : (EventData)
Returns:
  • (any or nil) The element’s action for this GUI event.
Usage:
event.on_gui_click(function(e)
  local action = gui.read_action(e)
  if action then
    -- do stuff
  end
end)
# build(parent, structures)

Build a GUI based on the given structure(s).

Parameters: Returns:
# update(elem, updates)

Update an existing GUI based on a given structure.

Parameters:
# get_tags(elem)

Retrieve a GUI element’s tags.

These tags are automatically written to and read from a subtable keyed by mod name, preventing conflicts.

If no tags exist, this function will return an empty table.

Parameters: Returns:
# set_tags(elem, tags)

Set (override) a GUI element’s tags.

These tags are automatically written to and read from a subtable keyed by mod name, preventing conflicts.

Parameters:
# delete_tags(elem)

Delete a GUI element’s tags.

These tags are automatically written to and read from a subtable keyed by mod name, preventing conflicts.

Parameters:
# update_tags(elem, updates)

Perform a shallow merge on a GUI element’s tags.

These tags are automatically written to and read from a subtable keyed by mod name, preventing conflicts.

Only the top level will be updated. If deep updating is needed, use gui-beta.get_tags and table.deep_merge, then gui-beta.set_tags.

Parameters:

Concepts

# GuiBuildStructure

A series of nested tables used to build a GUI.

This is an extension of LuaGuiElement, providing new features and options.

This inherits all required properties from its base LuaGuiElement, i.e. if the type field is sprite-button, the GuiBuildStructure must contain all the fields that a sprite-button LuaGuiElement requires.

There are a number of new fields that can be applied to a GuiBuildStructure depending on the type:

Usage:
gui.build(player.gui.screen, {
  {
    type = "frame",
    direction = "vertical",
    ref  =  {"window"},
    actions = {
      on_closed = {gui = "demo", action = "close"}
    },
    children = {
      -- titlebar
      {type = "flow", ref = {"titlebar", "flow"}, children = {
        {type = "label", style = "frame_title", caption = "Menu", ignored_by_interaction = true},
        {type = "empty-widget", style = "flib_titlebar_drag_handle", ignored_by_interaction = true},
        {
          type = "sprite-button",
          style = "frame_action_button",
          sprite = "utility/close_white",
          hovered_sprite = "utility/close_black",
          clicked_sprite = "utility/close_black",
          ref = {"titlebar", "close_button"},
          actions = {
            on_click = {gui = "demo", action = "close"}
          }
        }
      }},
      {type = "frame", style = "inside_deep_frame_for_tabs", children = {
        {type = "tabbed-pane", tabs = {
          {
            tab = {type = "tab", caption = "1"},
            content = {type = "table", style = "slot_table", column_count = 10, ref = {"tables", 1}}
          },
          {
            tab = {type = "tab", caption = "2"},
            content = {type = "table", style = "slot_table", column_count = 10, ref = {"tables", 2}}
          }
        }}
      }}
    }
  }
})
# GuiUpdateStructure

A series of nested tables used to update a GUI.

  • cb : (function) A callback to run on this GUI element. The callback will be passed a LuaGuiElement as its first parameter. (optional)
  • style : (string) The new style that the element should use. (optional)
  • style_mods : (table) A key –> value dictionary defining modifications to make to the element’s style. Available properties are listed in LuaStyle. (optional)
  • elem_mods : (table) A key –> value dictionary defining modifications to make to the element. Available properties are listed in LuaGuiElement. (optional)
  • children : (GuiUpdateStructure[]) GuiUpdateStructures to apply to the children of this LuaGuiElement. (optional)
  • tabs : (TabAndContent[]) TabAndContents to apply to the tabs of this LuaGuiElement. (optional)
Usage:
gui.update(
  my_frame,
  {
    elem_mods = {caption = "Hello there!"},
    children = {
      {children = {
        tabs = {
          {tab = {elem_mods = {badge_text = "69"}}, content = {...}},
          {content = {...}}
        }
      }}
    }
  }
)
# GuiElementActions

A mapping of GUI event name –> action message.

Each key is a GUI event name (on_gui_click, on_gui_elem_changed, etc.) with the _gui part removed. For example, on_gui_click will become on_click.

Each value is a custom set of data that gui-beta.read_action will return when that GUI event is fired and passes this GUI element. This data may be of any type, as long as it is truthy.

Actions are kept under a flib subtable in the element’s mod-specific tags subtable, retrievable with gui-beta.get_tags. Because of this, there is no chance of accidental mod action overlaps, so feel free to use generic actions such as “close” or “open”.

A common format for a mod with multiple GUIs might be to give each GUI a name, and write the actions as shown below.

Usage:
gui.build(player.gui.screen, {
  {
    type = "frame",
    caption = "My frame",
    actions = {
      on_click = {gui = "my_gui", action = "handle_click"},
      on_closed = {gui = "my_gui", action = "close"}
    }
  }
})
# TabAndContent

A table representing a tab <–> content pair.

When used in gui-beta.build, both fields are required. When used in gui-beta.update, both fields are optional.