Gui core

Core Module - Gui

Usage

-- Making the base button concept
local button =
Gui.new_concept() -- Make a new empty concept
:save_as('button') -- Save it as Gui.concepts.button so it can be used in other files
:new_event('on_click',defines.events.on_gui_click) -- Add an on click event for this concept
:new_property('tooltip') -- Add a property with the default setter method called tooltip
:new_property('caption',function(properties,value) -- Add a property with a custom setter method called caption
    properties.caption = value
    properties.sprite = nil
    properties.type = 'button'
end)
:new_property('sprite',function(properties,value) -- Add a property with a custom setter method called sprite
    properties.image = value
    properties.caption = nil
    properties.type = 'sprite-button'
end)
:define_draw(function(properties,parent,element) -- Add the draw function to create the element from the concept
    -- Properties will include all the information that you need to draw the element
    -- Parent is the parent element for the element, this may have been altered by previous draw functions
    -- Element is the current element being made, this may have a nil value, if it is nil then this is the first draw function
    if properties.type == 'button' then
        element = parent.add{
            type = properties.type,
            name = properties.name,
            caption = properties.caption,
            tooltip = properties.tooltip
        }

    else
        element = parent.add{
            type = properties.type,
            name = properties.name,
            sprite = properties.sprite,
            tooltip = properties.tooltip
        }

    end

    -- If you return element or parent then their values will be updated for the next draw function in the chain
    -- It is best practice to always return the values if you have made any changes to them
    return element, parent
end)
-- Making a new button which has a custom style
local custom_button =
Gui.new_concept('button') -- We can use button here since we used save as on the concept
-- button:clone() -- If we had not used save as then this is how we would use it as a base
:set_caption('Custom Button') -- Set the caption of the concept, this is possible as we added caption as a property
:set_tooltip('Only admins can press this button') -- Set the tooltip of the concept, this is possible as we added tooltip as a property
:on_click(function(event) -- Register a handler to the click event we added with new event
    if not event.player.admin then
        event.player.print('You must be admin to use this button')
    end
end)
:new_event('on_admin_clicked',defines.events.on_gui_click,function(event) -- Add a click event which has a filter function
    return event.player.admin -- Check if the player is admin
end)
:on_admin_clicked(function(event) -- Register a handler to the admin click event we have just created
    -- The admin click event is only an example, because of how sinmple the filter is we could have just used an if else statement
    game.print(event.player.name..' pressed my admin button')
end)
-- Drawing a concept
custom_button:draw(game.player.gui.left)

Elements

button Clickable elements that fire on_gui_click when clicked.
checkbox Clickable elements with a cross in the middle that can be turned off or on.
dropdown A drop down list of other elements.
elem_button A button that lets the player pick one of an: item, entity, tile, or signal similar to the filter-select window.
empty A empty widget that just exists.
flow Invisible containers that lay out children either horizontally or vertically.
frame Grey semi-transparent boxes that contain other elements.
label A piece of text.
line A vertical or horizontal line.
progress_bar Indicate progress by displaying a partially filled bar.
scroll Similar to a flow but includes the ability to show and use scroll bars.
slider A number picker.
table An invisible container that lays out children in a specific number of columns.
text_box A multi-line text box that supports selection and copy-paste.
text_field Boxes of text the user can type in.

Dropdowns

set_dropdown_value(element, value) Selects the index of a dropdown with this value
get_dropdown_value(element) Gets the selected item value of a dropdown
add_dropdown_items(element[, start_index], new_items) Adds the given items into the list of items for this dropdown

Progress Bars

progress_bar:increment(element[, amount=1]) Will increase the progress of a progress bar based on this concept, if the concept has an instance store then element acts as the category, if you have a combined store it will NOT update all instances
progress_bar:decrement(element[, amount=1]) Will decrease the progress of a progress bar based on this concept, if the concept has an instance store then element acts as the category, if you have a combined store it will NOT update all instances
progress_bar:reset(element) Resets the progress back to 0% for this element, if the concept has an instance store then element acts as the category, if you have a combined store it will NOT update all instances
increment_progress_bar(element[, amount=0.01]) Increment any progress bar by the given percentage
decrement_progress_bar(element[, amount=0.01]) Decrement any progress bar by the given percentage

Concept Control

require_concept(concept_name) Loads a concept from the concepts file
require_style(style_name) Loads a set of concepts from the styles file
get_concept(name) Gets a gui concept from name, id, or its self
Prototype:save_as(save_name) Used to save the concept to the main gui module to allow access from other files
new_concept([base_concept]) Returns a new gui concept, option to provide a base concept to copy properties and draw functions from
draw_concept(concept, parent) Used to draw a concept to a parent element

Element Control

get_player_from_element(element) Gets the player who owns this element
valid(element) Simple check for if an element is valid
destroy(element) Destroies and element if it is valid
find(element, ...) Finds and returns a gui element if it is valid from a long chain of element names or concepts
exists Checks if a gui element exists or not, returns it if found else the path where it failed
toggle_enabled(element) Toggles the enabled state of an element
toggle_visible(element) Toggles the visible state of an element
set_padding(element[, up=0][, down=0][, left=0][, right=0]) Sets the padding for a gui element

Store Categories

categorize_by_player(element) A categorize function to be used with add_store, each player has their own category
categorize_by_force(element) A categorize function to be used with add_store, each force has its own category
categorize_by_surface(element) A categorize function to be used with add_store, each surface has its own category

Concept Base

Prototype:clone(concept_name) Used to copy all the settings from one concept to another and removing links to the orginal
Prototype:define_clone(clone_callback) Use to add your own callbacks to the clone function, for example adding to a local table
Prototype:save_as(save_name) Used to save the concept to the main gui module to allow access from other files
Prototype:debug(name) Sets a debug name that can be used with error handlers
Prototype:new_event(event_name[, factorio_event][, event_condition]) Adds a new event trigger to the concept which can be linked to a factorio event
Prototype:on_custom_event(handler) Adds a custom event handler, replace with the name of the event
Prototype:raise_event(event_name[, event={}][, from_factorio=false]) Raises a custom event, folowing keys included automaticlly: concept, event name, game tick, player from player_index, element if valid
Prototype:new_property(property_name[, setter_callback][, default]) Adds a new property to the concept, such as caption, tooltip, or some custom property you want to control
Prototype:set_custom_property(value) Sets a new value for a property, triggers setter method if provided, replace with property name
Prototype:define_draw(draw_callback) Used to define how the concept is turned into an ingame element or "instance" as we may refer to them
Prototype:draw(parent_element[, override_name]) Calls all the draw functions in order to create this concept in game; will also store and sync the instance if stores are used

Concept Instances

Prototype:define_instance_store([category_callback]) Adds an instance store to the concept; when a new instance is made it is stored so you can access it later
Prototype.get_instances([category]) Gets all insatnces in a category, category may be nil to return all
Prototype.add_instance(element[, category]) Adds an instance to this concept, used automatically during concept:draw
Prototype.update_instances([category], update_callback) Applies an update function to all instances, simialr use to what table.forEach would be

Concept Data

Prototype:define_data_store([category_callback]) Adds a data store to this concept which allows you to store synced/percistent data between instances
Prototype.get_data([category]) Gets the data that is stored for this category
Prototype.set_data([category], value) Sets the data that is stored for this category
Prototype.clear_data([category]) Clears the data that is stored for this category
Prototype.update_data([category], update_callback) Updates the data that is stored for this category

Concept Combined Instances

Prototype:define_combined_store([category_callback], sync_callback) Used to add a both instance and data store which are linked together, new instances are synced to the current value, changing the stored value will change all instances
Prototype.sync_instance(element) Will sync an instance to match the stored value based on the given sync callback

Tests

run_tests(player[, category]) Runs a set of gui tests to ensure that the system is working

Elements

# button

Clickable elements that fire on_gui_click when clicked.

Properties / Events:
  • on_click : fired when the player clicks the button
  • on_left_click : fired when the player clicks with the right mouse button
  • on_left_click : fired when the player clicks with the right mouse button
  • caption : (string or LocalisedString) the message that is shown on the button
  • tooltip : (string or LocalisedString) the tooltip that shows when a player hovers over the button
  • sprite : (SpritePath) upto three sprites in the order: default, hovered, clicked
Usage:
-- Making a basic button
local basic_button =
Gui.new_concept('button')
:set_caption('Basic Button')
:set_tooltip('Basic button')
:on_click(function(event)
    event.player.print('You pressed basic button!')
end)
-- Making a sprite button
local sprite_button =
Gui.new_concept('button')
:set_sprite('utility/warning_icon')
:set_tooltip('Sprite button')
:on_click(function(event)
    event.player.print('You pressed sprite button!')
end)
# checkbox

Clickable elements with a cross in the middle that can be turned off or on.

Properties / Events:
  • on_state_changed : fired when the state of the element is changed
  • caption : (string or LocalisedString) the message that is shown next to the checkbox
  • tooltip : (string or LocalisedString) the tooltip that shows when a player hovers over the checkbox
  • default : (boolean or function) the default state of this checkbox, or a function which returns the default state
  • use_radio : (boolean) setting to true will use radio buttons rather than checkboxs
Usage:
-- Making a basic checkbox
local basic_checkbox =
Gui.new_concept('checkbox')
:set_caption('Basic Checkbox')
:set_tooltip('Basic checkbox')
:on_state_changed(function(event)
    event.player.print('Basic checkbox is now: '..tostring(event.element.state))
end)
# dropdown

A drop down list of other elements.

Properties / Events:
  • on_selection_changed : fired when the selected value is changed
  • default : (string, LocalisedString or function) the option which is selected by default, or a function which returns the default
  • use_list_box : (boolean) when true a list box will be used rather than a dropdown menu
  • static_items : (nil or table) when called with a table the values will be added as items for the dropdown, if called with nil then all items are cleared
  • dynamic_items : (function) the given function will be called to return a list of items and optional start index to add items to the dropdown when it is first drawn
Usage:
-- Making a basic dropdown
local static_dropdown =
Gui.new_concept('dropdown')
:set_static_items{'Option 1','Option 2','Option 3'}
:on_selection_changed(function(event)
    local value = Gui.get_dropdown_value(event.element)
    event.player.print('Static dropdown is now: '..value)
end)
-- Making a dropdown with dynamic items, example is name of online players
local dynamic_dropdown =
Gui.new_concept('dropdown')
:set_dynamic_items(function(element)
    local items = {}
    for _,player in pairs(game.connected_players) do
        items[#items+1] = player.name
    end
    return items
end)
:on_selection_changed(function(event)
    local value = Gui.get_dropdown_value(event.element)
    event.player.print('Dynamic dropdown is now: '..value)
end)
# elem_button

A button that lets the player pick one of an: item, entity, tile, or signal similar to the filter-select window.

Properties / Events:
  • on_selection_changed : fired when the selected value is changed
  • default : (string, SignalID or function) the option which is selected by default, or a function which returns the default
  • elem_type : (string) the type of elem selection that this is, default is item selection
Usage:
-- Making a basic elem button
local basic_elem_button =
Gui.new_concept('elem_button')
:on_selection_changed(function(event)
    event.player.print('Basic elem button is now: '..event.element.elem_value)
end)
# empty

A empty widget that just exists.

The root GUI element screen is an empty-widget.

Properties / Events:
  • style : (string) the style that the element will have
Usage:
-- Making a draggable space styled widget
local draggable_space =
Gui.new_concept('empty')
:set_style('draggable_space')
# flow

Invisible containers that lay out children either horizontally or vertically.

The root GUI elements (top, left and center; see LuaGui) are flows.

Properties / Events:
  • direction : (string) the direction that children will be added
Usage:
-- Making a basic flow, contains a label with hello world
local basic_flow =
Gui.new_concept('flow')
:define_draw(function(properties,parent,element)
    element.add{
        type = 'label',
        caption = 'Hello, World!'
    }
end)
# frame

Grey semi-transparent boxes that contain other elements.

They have a caption, and, just like flows, they lay out children either horizontally or vertically.

Properties / Events:
  • title : (string or LocalisedString) the title that will show in the frame
  • direction : (string) the direction that children will be added
Usage:
-- Making a basic frame, contains a label with hello world
local basic_frame =
Gui.new_concept('frame')
:set_title('Basic Frame')
:define_draw(function(properties,parent,element)
    element.add{
        type = 'label',
        caption = 'Hello, World!'
    }
end)
# label

A piece of text.

Properties / Events: Usage:
-- Making a basic label
local basic_label =
Gui.new_concept('label')
:set_caption('Hello, World!')
# line

A vertical or horizontal line.

Properties / Events:
  • direction : (string) the direction that children will be added
Usage:
-- Making a basic frame, contains a label with hello world
local basic_line =
Gui.new_concept('line')
# progress_bar

Indicate progress by displaying a partially filled bar.

Properties / Events:
  • on_completion : fired when increment reaches the maxium value set by set_maximum
  • tooltip : (string or LocalisedString) the tooltip that will show for this element
  • maximum : (number) the maxium amount an instance can be increased, default 100
  • delay_completion : (boolean) when true the progress will be completed untill after the maximum rather than at the maximum
  • inverted : (boolean) although this will NOT effect how you use the functions it will make the element start full and reduce as you call increase, note issues with 0 detections
Usage:
-- Making a basic progress bar, will increase when pressed then will reset when full
local basic_progress_bar =
Gui.new_concept('progress_bar')
:set_tooltip('Basic progress bar')
:set_maximum(5)
:new_event('on_click',defines.events.on_gui_click)
:on_click(function(event)
    event.concept:increment(event.element)
end)
:set_delay_completion(true)
:on_completion(function(event)
    event.concept:reset(event.element)
end)
# scroll

Similar to a flow but includes the ability to show and use scroll bars.

Properties / Events:
  • horizontal_scroll : (string) the horizontal scroll policy for this scroll pane
  • vertical_scroll : (string) the vertical scroll policy for this scroll pane
Usage:
-- Making a basic flow, contains a label with hello world
local basic_scroll =
Gui.new_concept('scroll')
:define_draw(function(properties,parent,element)
    element.style.hieght = 50
    for i = 1,10 do
        element.add{
            type = 'label',
            caption = i
        }
    end
end)
# slider

A number picker.

Properties / Events:
  • on_value_changed : fired when the value of the slider is changed
  • value_step : (number) the minimum amount by which the value of the slider can be changed
  • default : (number or function) the default value of the slider or a function which returns the default value
  • discrete_slider : (boolean) makes this slider a discrete slider, this means that the slider button will stop at the same interval as the values do
  • range : (number or function) accepts two params the minimum and the maximum for this slider, or a single function to return both
Usage:
-- Making a basic slider
local basic_slider =
Gui.new_concept('slider')
:set_range(1,10)
:on_value_changed(function(event)
    event.player.print('Basic slider is now: '..event.element.slider_value)
end)
-- Making a discrete_slider
local discrete_slider =
Gui.new_concept('slider')
:set_range(1,10)
:set_value_step(1)
:set_discrete_slider(true)
:on_value_changed(function(event)
    event.player.print('Interval slider is now: '..event.element.slider_value)
end)
# table

An invisible container that lays out children in a specific number of columns.

Column width is given by the largest element contained in that row.

Properties / Events:
  • column_count : (number or function) the column count of the table or a function that returns the count being given then parent element
  • vertical_lines : (boolean) when true vertical lines will be drawn on the table
  • horizontal_lines : (boolean) when true horizontal lines will be drawn on the table
  • header_lines : (boolean) when true horizontal lines will be drawn under the first row
  • vertical_centering : (boolean) when true element will be vertically centered with in the table
Usage:
-- Making a basic table, contains 25 labels
local basic_table =
Gui.new_concept('table')
:set_column_count(5)
:define_draw(function(properties,parent,element)
    for i = 1,25 do
        element.add{
            type = 'lable',
            caption = i
        }
    end
end)
# text_box

A multi-line text box that supports selection and copy-paste.

Properties / Events:
  • on_text_changed : fired when the text within the text box is changed
  • tooltip : (string or LocalisedString) the tooltip that shows when a player hovers over the text box
  • default : (string or function) the default text that will appear in the text box, or a function that returns it
  • rich_text : (defines.rich_text_setting) how this element handles rich text
  • clear_on_rmb : (boolean) if the text box will be cleared and forcused on a right click
  • is_selectable : (boolean) when true the text inside the box can be selected
  • has_word_wrap : (boolean) when true the text will wrap onto the next line if it reachs the end
  • is_read_only : (boolean) when true the text inside the box can not be edited by the player
Usage:
-- Making a text box
local basic_text_box =
Gui.new_concept('text_box')
:set_default('I am the text that will show in the text box')
-- Making a text box which can be edited
local editible_text_box =
Gui.new_concept('text_box')
:set_is_read_only(false)
:set_default('I am the text that will show in the text box')
:on_confirmation(function(event)
    event.player.print('Editible text box is now: '..event.element.text)
end)
# text_field

Boxes of text the user can type in.

Properties / Events:
  • on_text_changed : fired when the text within the text field is changed
  • on_confirmation : fired when the player presses enter with the text field forcused
  • tooltip : (string or LocalisedString) the tooltip that shows when a player hovers over the text field
  • default : (string or function) the default text that will appear in the text field, or a function that returns it
  • rich_text : (defines.rich_text_setting) how this element handles rich text
  • clear_on_rmb : (boolean) if the text field will be cleared and forcused on a right click
  • lose_forcus : (boolean) if the text field will lose forcus after the confirmation event
  • is_number : (boolean) if this text field contains a number value, can be ignored if is_decimal or is_negitive is used
  • is_decimal : (boolean) if this text field contains a decimal value
  • is_negative : (boolean) if this text field contains a negative value
  • is_password : (boolean) if this text field contains a password value
Usage:
-- Making a text field
local basic_text_field =
Gui.new_concept('text_field')
:on_confirmation(function(event)
    event.player.print('Basic text field is now: '..event.element.text)
end)
-- Making a text field which will clear on right click and un forcus on confirmation
local better_text_field =
Gui.new_concept('text_field')
:set_clear_on_rmb(true)
:set_lose_forcus(true)
:on_confirmation(function(event)
    event.player.print('Better text field is now: '..event.element.text)
end)
-- Making a decimal input
local decimal_text_field =
Gui.new_concept('text_field')
:set_is_decimal(true)
:on_confirmation(function(event)
    event.player.print('Decimal text field is now: '..event.element.text)
end)

Dropdowns

# set_dropdown_value(element, value)

Selects the index of a dropdown with this value

Parameters: Returns:
  • (boolean) if an item with this value was found
Usage:
-- Selecting the item with the value 'foo'
Gui.set_dropdown_value(element,'foo')
# get_dropdown_value(element)

Gets the selected item value of a dropdown

Parameters:
  • element : (LuaGuiElement) the dropdown that you want the selected value of
Returns: Usage:
-- Getting the selected value
local selected_value = Gui.get_dropdown_value(element)
# add_dropdown_items(element[, start_index], new_items)

Adds the given items into the list of items for this dropdown

Parameters:
  • element : (LuaGuiElement) the dropdown that you want to add the items to
  • start_index : (number) the index at which the items will be added, if not given appened to the end (optional)
  • new_items : (table) the list of new items that you want to add
Returns:
  • (table) the list of items that the element now has
Usage:
-- Add the items 'foo' and 'bar' to the end
Gui.add_dropdown_items(element,{'foo','bar'})
-- Add the items 'foo' and 'bar' to the start
Gui.add_dropdown_items(element,1,{'foo','bar'})

Progress Bars

# progress_bar:increment(element[, amount=1])

Will increase the progress of a progress bar based on this concept, if the concept has an instance store then element acts as the category, if you have a combined store it will NOT update all instances

Parameters:
  • element : (LuaGuiElement or string) either the element that is changed or the category that is being changed (only if an instance store is defined)
  • amount : (number) the amount that will bar will increase, note that this amount must be less than the max (default: 1)
Returns:
  • (number or nil) the new value of the element, use this to sync a data store, if the return is nil then either a instance store was used or the new value may have changed
Usage:
-- Incrementing progress bar with no instance store
local new_value = progress_bar:increment(element)
-- Incrementing progress bar with an instance store
progress_bar:increment(category)
# progress_bar:decrement(element[, amount=1])

Will decrease the progress of a progress bar based on this concept, if the concept has an instance store then element acts as the category, if you have a combined store it will NOT update all instances

Parameters:
  • element : (LuaGuiElement or string) either the element that is changed or the category that is being changed (only if an instance store is defined)
  • amount : (number) the amount that will bar will decrease, note that this amount must be less than the max (default: 1)
Returns:
  • (number) the new value of the element, use this to sync a data store, if the return is nil then either a instance store was used or the new value may have changed
Usage:
-- Decrementing progress bar with no instance store
local new_value = progress_bar:decrement(element)
-- Decrementing progress bar with an instance store
progress_bar:decrement(category)
# progress_bar:reset(element)

Resets the progress back to 0% for this element, if the concept has an instance store then element acts as the category, if you have a combined store it will NOT update all instances

Parameters:
  • element : (LuaGuiElement or string) either the element that is changed or the category that is being changed (only if an instance store is defined)
Returns:
  • (number or nil) the new value of the element, use this to sync a data store, if the return is nil then either a instance store was used or the new value may have changed
Usage:
-- Reseting a progress bar with no instance store
local new_value = progress_bar:reset(element)
-- Reseting a progress bar with an instance store
progress_bar:reset(category)
# increment_progress_bar(element[, amount=0.01])

Increment any progress bar by the given percentage

Parameters:
  • element : (LuaGuiElement) the progress bar that you want to update
  • amount : (number) the percentage that you want to increment the progress bar by (default: 0.01)
Returns:
  • (boolean) true if the bar is now full
Usage:
-- Increment any progress bar by 10%
Gui.increment_progress_bar(element,0.1)
# decrement_progress_bar(element[, amount=0.01])

Decrement any progress bar by the given percentage

Parameters:
  • element : (LuaGuiElement) the progress bar that you want to update
  • amount : (number) the percentage that you want to decrement the progress bar by (default: 0.01)
Returns:
  • (boolean) true if the bar is now empty
Usage:
-- Decrement any progress bar by 10%
Gui.decrement_progress_bar(element,0.1)

Concept Control

# require_concept(concept_name)

Loads a concept from the concepts file

Parameters:
  • concept_name : (string) the name of the concept to require
Usage:
-- Load a base concept
Gui.require_concept('frame') --- @dep Gui.concept.frame
# require_style(style_name)

Loads a set of concepts from the styles file

Parameters:
  • style_name : (string) the name of the style to require
Usage:
-- Load a base style
Gui.require_concept('expgaming') --- @dep Gui.style.frame
# get_concept(name)

Gets a gui concept from name, id, or its self

Parameters: Usage:
-- Getting a gui concept
local button = Gui.get_concept('Button')
# Prototype:save_as(save_name)

Used to save the concept to the main gui module to allow access from other files

Parameters:
  • save_name : (string) the new name of the concept
Usage:
-- Save a concept to allow access in another file
button:save_as('button')
-- Access concept after being saved
Gui.concepts.button
Gui.get_concept('button')
# new_concept([base_concept])

Returns a new gui concept, option to provide a base concept to copy properties and draw functions from

Parameters:
  • base_concept : (string, number or table) the concept that you want to copy the details of (optional)
Usage:
-- Making a new button, see module usage
local button = Gui.new_concept('Button')
# draw_concept(concept, parent)

Used to draw a concept to a parent element

Parameters:
  • concept : (string, number or table) the name of the concept that you want to draw
  • parent : (LuaGuiElement) the element that will act as a parent for the new element
Returns: Usage:
-- Drawing a new element
Gui.draw_concept('Button',element)

Element Control

# get_player_from_element(element)

Gets the player who owns this element

Parameters:
  • element : (LuaGuiElement) the element that you want to get the player of
Returns:
  • (LuaPlayer) the player who owns this element
Usage:
-- Getting the player of an element
local player = Gui.get_player_from_element(element)
# valid(element)

Simple check for if an element is valid

Parameters:
  • element : (LuaGuiElement) the element that you want to check is valid
Returns:
  • (boolean) true if the element is valid
Usage:
-- Return if not valid
if not Gui.valid(element) then return end
# destroy(element)

Destroies and element if it is valid

Parameters: Returns:
  • (boolean) true if the element was valid and was destoried
Usage:
-- Destoring an element
Gui.destroy(element)
# find(element, ...)

Finds and returns a gui element if it is valid from a long chain of element names or concepts

Parameters:
  • element : (LuaGuiElement) the root element to start checking from
  • ... : (string or table) element names or element concepts that point to your element
Returns:
  • (boolean) if the element was found, failed
  • (string) the path of the element that the search stoped at
Or
Usage:
-- Getting the center gui
local exists, center = Gui.find(player,'gui','center')
# exists

Checks if a gui element exists or not, returns it if found else the path where it failed

  • element : (LuaGuiElement) the root element to start checking from
  • ... : (string or table) element names or element concepts that point to your element
See also: Usage:
-- Getting the center gui
local exists, center = Gui.exists(player,'gui','center')
# toggle_enabled(element)

Toggles the enabled state of an element

Parameters:
  • element : (LuaGuiElement) the element that you want to toggle the enabled state of
Returns:
  • (boolean) the new enabled state of the element
Usage:
-- Toggle the enabled state of an element
Gui.toggle_enabled(element)
# toggle_visible(element)

Toggles the visible state of an element

Parameters:
  • element : (LuaGuiElement) the element that you want to toggle the visible state of
Returns:
  • (boolean) the new visible state of the element
Usage:
-- Toggle the visible state of an element
Gui.toggle_visible(element)
# set_padding(element[, up=0][, down=0][, left=0][, right=0])

Sets the padding for a gui element

Parameters:
  • element : (LuaGuiElement) the element to set the padding for
  • up : (number or boolean) the amount of padding on the top, true leaves unchanged (default: 0)
  • down : (number or boolean) the amount of padding on the bottom, true leaves unchanged (default: 0)
  • left : (number or boolean) the amount of padding on the left, true leaves unchanged (default: 0)
  • right : (number or boolean) the amount of padding on the right, true leaves unchanged (default: 0)
Usage:
-- Remove all padding of an element
Gui.set_padding(element)
-- Remove side padding but keep vertical padding
Gui.set_padding(element,true,true)
-- Remove all padding but set right to 2
Gui.set_padding(element,false,false,false,2)

Store Categories

# categorize_by_player(element)

A categorize function to be used with add_store, each player has their own category

Parameters:
  • element : (LuaGuiElement) the element that will be converted to a string
Returns:
  • (string) the player's name who owns this element
Usage:
-- Storing data on a per player basis, can be used with instances
Gui.get_concept('CustomButton')
:define_data_store(Gui.categorize_by_player)
# categorize_by_force(element)

A categorize function to be used with add_store, each force has its own category

Parameters:
  • element : (LuaGuiElement) the element that will be converted to a string
Returns:
  • (string) the player's force name who owns this element
Usage:
-- Storing data on a per force basis, can be used with instances
Gui.get_concept('CustomButton')
:define_data_store(Gui.categorize_by_force)
# categorize_by_surface(element)

A categorize function to be used with add_store, each surface has its own category

Parameters:
  • element : (LuaGuiElement) the element that will be converted to a string
Returns:
  • (string) the player's surface name who owns this element
Usage:
-- Storing data on a per surface basis, can be used with instances
Gui.get_concept('CustomButton')
:define_data_store(Gui.categorize_by_surface)

Concept Base

# Prototype:clone(concept_name)

Used to copy all the settings from one concept to another and removing links to the orginal

Parameters:
  • concept_name : (string) the name of the new concept; must be unique
Returns:
  • (GuiConcept) the base for building a custom gui
Usage:
-- Clones the base Button concept to make a alternative button
local custom_button =
Gui.get_concept(Gui.concepts.button):clone()
# Prototype:define_clone(clone_callback)

Use to add your own callbacks to the clone function, for example adding to a local table

Parameters:
  • clone_callback : (function) the function which is called with the concept to have something done to it
Returns:
  • (table) self to allow chaining
Usage:
-- Adding concept to a local table
local buttons = {}
local button =
Gui.get_concept('Button')
:define_clone(function(concept)
    buttons[concept.name] = concept
end)
# Prototype:save_as(save_name)

Used to save the concept to the main gui module to allow access from other files

Parameters:
  • save_name : (string) the new name of the concept
Usage:
-- Save a concept to allow access in another file
button:save_as('button')
-- Access concept after being saved
Gui.concepts.button
Gui.get_concept('button')
# Prototype:debug(name)

Sets a debug name that can be used with error handlers

Parameters:
  • name : (string) the name that will be used in error messages
Returns:
  • (self) to allow chaining
Usage:
-- Set the debug name
unsaved_concept:debug('Example button')
# Prototype:new_event(event_name[, factorio_event][, event_condition])

Adds a new event trigger to the concept which can be linked to a factorio event

Parameters:
  • event_name : (string) the name of the event to add, must be unique, recomented to start with "on_"
  • factorio_event : (defines.events) when given will fire the custom event when the factorio event is raised (optional)
  • event_condition : (function) used to filter when a factorio event triggers the custom event; if the event contains a reference to an element then names are automatically filtered (optional)
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Adds an on_admin_clicked event to fire when ever an admin clicks the button
local custom_button =
Gui.get_concept('Button'):clone('CustomButton')
:new_event('on_admin_clicked',defines.events.on_gui_click,function(event)
    return event.player.admin -- only raise custom event when an admin clicks the button
end)
# Prototype:on_custom_event(handler)

Adds a custom event handler, replace with the name of the event

Parameters:
  • handler : (function) the function which will recive the event
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- When an admin clicks the button a message is printed
local custom_button =
Gui.get_concept('CustomButton')
:on_admin_clicked(function(event)
    game.print(event.player.name..' pressed my admin button')
end)
# Prototype:raise_event(event_name[, event={}][, from_factorio=false])

Raises a custom event, folowing keys included automaticlly: concept, event name, game tick, player from player_index, element if valid

Parameters:
  • event_name : (string) the name of the event that you want to raise
  • event : (table) table containg data you want to send with the event, some keys already included (default: {})
  • from_factorio : (boolean) internal use, if the raise came from the factorio event handler (default: false)
Usage:
-- Raising the custom event on_admin_clicked
local custom_button =
Gui.get_concept('CustomButton')

-- Note that this is an example and would not work due it expecting a valid element for event.element
-- this will however work fine if you can provide all expected keys, or its not linked to any factorio event
custom_button:raise_event('on_admin_clicked',{
    player_index = game.player.index
})
# Prototype:new_property(property_name[, setter_callback][, default])

Adds a new property to the concept, such as caption, tooltip, or some custom property you want to control

Parameters:
  • property_name : (string) the name of the new property, must be unique
  • setter_callback : (function) this function is called when set is called, if not provided then key in concept.properties is updated to new value (optional)
  • default : (any) use this as the default value, will call the setter callback if defined (optional)
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Adding caption, sprite, and tooltip to the base button concept
local button =
Gui.get_concept('Button')
:new_property('tooltip')
:new_property('caption',nil,function(properties,value)
    properties.caption = value
    properties.sprite = nil
    properties.type = 'button'
end)
:new_property('sprite',nil,function(properties,value)
    properties.image = value
    properties.caption = nil
    properties.type = 'sprite-button'
end)
# Prototype:set_custom_property(value)

Sets a new value for a property, triggers setter method if provided, replace with property name

Parameters:
  • value : (any) the value that you want to set for this property
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Setting the caption on the base button concept after a cloning
local custom_button =
Gui.get_concept('Button')
:set_caption('Default Button')
-- In our examples CustomButton is cloned from Button, this means the caption property already exists
-- note that what ever values that properties have at the time of cloning are also copied
local custom_button =
Gui.get_concept('CustomButton')
:set_caption('Custom Button')
# Prototype:define_draw(draw_callback)

Used to define how the concept is turned into an ingame element or "instance" as we may refer to them

Parameters:
  • draw_callback : (function) the function that will be called to draw/update the instance; this function must return the instance or the new acting instance
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Adding the draw define for the base button concept, we then return the element
local button =
Gui.get_concept('Button')
:define_draw(function(properties,parent,element)
    -- Properties will include all the information that you need to draw the element
    -- Parent is the parent element for the element, this may have been altered by previous draw functions
    -- Element is the current element being made, this may have a nil value, if it is nil then this is the first draw function
    -- You can also pass any other arguments that you want to this function from the draw call
    if properties.type == 'button' then
        element = parent.add{
            type = properties.type,
            name = properties.name,
            caption = properties.caption,
            tooltip = properties.tooltip
        }

    else
        element = parent.add{
            type = properties.type,
            name = properties.name,
            sprite = properties.sprite,
            tooltip = properties.tooltip
        }

    end

    -- If you return element or parent then their values will be updated for the next draw function in the chain
    -- It is best practice to always return the values if you have made any changes to them
    return element, parent
end)
# Prototype:draw(parent_element[, override_name])

Calls all the draw functions in order to create this concept in game; will also store and sync the instance if stores are used

Parameters:
  • parent_element : (LuaGuiElement) the element that the concept will use as a base
  • override_name : (string) when given this will be the name of the element rather than the concept id (optional)
Returns:
  • (LuaGuiElement) the element that was created and then passed though and returned by the draw functions
Usage:
-- Drawing the custom button concept
local custom_button =
Gui.get_concept('CustomButton')

-- Note that the draw function from button was cloned, so unless we want to alter the base button we dont need a new draw define
custom_button:draw(game.player.gui.left)

Concept Instances

# Prototype:define_instance_store([category_callback])

Adds an instance store to the concept; when a new instance is made it is stored so you can access it later

Parameters:
  • category_callback : (function) when given will act as a way to turn an element into a string to act as a key; keys returned can over lap (optional)
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Allowing storing instances of the custom button; stored by the players index
-- Note even thou this is a copy of Button; if Button had an instance store it would not be cloned over
local custom_button =
Gui.get_concept('CustomButton')
:define_instance_store(function(element)
    return element.player_index -- The instances are stored based on player id
end)
# Prototype.get_instances([category])

Gets all insatnces in a category, category may be nil to return all

Parameters:
  • category : (string or LuaGuiElement) the category to get, can only be nil if categories are not used (optional)
Returns:
  • (table) a table which contains all the instances
Usage:
-- Getting all the instances of the player with index 1
local custom_button =
Gui.get_concept('CustomButton')

custom_button.get_instances(1) -- player index 1
# Prototype.add_instance(element[, category])

Adds an instance to this concept, used automatically during concept:draw

Parameters:
  • element : (LuaGuiElement) the element that will be added as an instance
  • category : (string) the category to add this element under, if nil the category callback is used to assign one (optional)
Usage:
-- Adding an element as a instance for this concept, mostly for internal use
local custom_button =
Gui.get_concept('CustomButton')

custom_button.add_instance(element) -- normally not needed due to use in concept:draw
# Prototype.update_instances([category], update_callback)

Applies an update function to all instances, simialr use to what table.forEach would be

Parameters:
  • category : (string or LuaGuiElement) the category to get, can only be nil if categories are not used (optional)
  • update_callback : (function) the function which is called on each instance, recives other args passed to update_instances
Usage:
-- Changing the font color of all instances for player 1
local custom_button =
Gui.get_concept('CustomButton')

custom_button.update_instances(1,function(element)
    element.style.font_color = {r=1,g=0,b=0}
end)

Concept Data

# Prototype:define_data_store([category_callback])

Adds a data store to this concept which allows you to store synced/percistent data between instances

Parameters:
  • category_callback : (function) when given will act as a way to turn an element into a string to act as a key; keys returned can over lap (optional)
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Adding a way to store data for this concept; each player has their own store
-- Note even thou this is a copy of Button; if Button had an data store it would not be cloned over
local custom_button =
Gui.get_concept('CustomButton')
:define_data_store(function(element)
    return element.player_index -- The data is stored based on player id
end)
# Prototype.get_data([category])

Gets the data that is stored for this category

Parameters:
  • category : (string or LuaGuiElement) the category to get, can only be nil if categories are not used (optional)
Returns:
  • (any) the data that you had stored in this location
Usage:
-- Getting the stored data for player 1
local custom_button =
Gui.get_concept('CustomButton')

custom_button.get_data(1) -- player index 1
# Prototype.set_data([category], value)

Sets the data that is stored for this category

Parameters:
  • category : (string or LuaGuiElement) the category to set, can only be nil if categories are not used (optional)
  • value : (any) the data that you want to stored in this location
Usage:
-- Setting the data for player 1 to a table with two keys
local custom_button =
Gui.get_concept('CustomButton')

-- A table is used to show correct way to use a table with self.update_data
-- but a table is not required and can be any data, however upvalues may cause desyncs
custom_button.set_data(1,{
    clicks = 0,
    required_clicks = 100
}) -- player index 1
# Prototype.clear_data([category])

Clears the data that is stored for this category

Parameters:
  • category : (string or LuaGuiElement) the category to clear, can only be nil if categories are not used (optional)
Usage:
-- Clearing the data for player 1
local custom_button =
Gui.get_concept('CustomButton')

custom_button.clear_data(1) -- player index 1
# Prototype.update_data([category], update_callback)

Updates the data that is stored for this category

Parameters:
  • category : (string or LuaGuiElement) the category to clear, can only be nil if categories are not used (optional)
  • update_callback : (function) the function which is called to update the data
Usage:
-- Updating the clicks key in the concept data for player 1
local custom_button =
Gui.get_concept('CustomButton')

custom_button.update_data(1,function(tbl)
    tbl.clicks = tbl.clicks + 1 -- here we are incrementing the clicks by 1
end) -- player index 1
-- Updating a value when a table is not used, alterative to get set
-- so for this example assume that we did custom_button.set_data(1,0)
custom_button.update_data(1,function(value)
    return value + 1 -- here we are incrementing the value by 1, we may only be tracking clicks
end) -- player index 1

Concept Combined Instances

# Prototype:define_combined_store([category_callback], sync_callback)

Used to add a both instance and data store which are linked together, new instances are synced to the current value, changing the stored value will change all instances

Parameters:
  • category_callback : (function) when given will act as a way to turn an element into a string to act as a key; keys returned can over lap (optional)
  • sync_callback : (function) the function which is called to update an instance to match the store, this is called on all instances when concept.set_data or update_data is used
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Adding a check box which is a "global setting" synced between all players
local custom_button =
Gui.get_concept('checkbox'):clone('my_checkbox')
:set_caption('My Checkbox')
:set_tooltip('Clicking this check box will change it for everyone')
:on_state_changed(function(event)
    local element = event.element
    event.concept.set_data(element,element.state) -- Update the stored data to trigger an update of all other instances
end)
:define_combined_store(function(element,state) -- We could add a category function here if we wanted to
    element.state = state or false -- Note that the value passed may be nil if there is no stored value and no default set
end)
# Prototype.sync_instance(element)

Will sync an instance to match the stored value based on the given sync callback

Parameters:
  • element : (LuaGuiElement) the element that you want to have update
Usage:
-- Setting the caption of this element to be the same as the stored value
local custom_button =
Gui.get_concept('CustomButton')

-- Used internally when first draw and automatically when the store updates
custom_button.sync_instance(element)

Tests

# run_tests(player[, category])

Runs a set of gui tests to ensure that the system is working

Parameters:
  • player : (LuaPlayer) the player that the guis are made for and who recives the results
  • category : (string) when given only tests in this category are ran (optional)
Usage:
-- Run all gui tests
Gui.run_tests(game.player)