Gui core

Core Module - Gui

Usage

-- Making the base button concept
local button =
Gui.new_concept('Button')
:new_event('on_click',defines.events.on_gui_click)
: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)
:define_draw(function(properties,parent,element)
    -- Note that element might be nil if this is the first draw function
    -- in this case button is a new concept so we know this is the first function and element is nil
    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

    -- We must return the element or what we want to be seen as the instance, this is so other draw functions have access to it
    -- for example if our custom button defined a draw function to change the font color to red
    return element
end)
-- Makeing a alternative button based on the first
local custom_button =
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)
:set_caption('Custom Button')
:set_tooltip('Only admins can press this button')
:on_click(function(event)
    if not event.player.admin then
        event.player.print('You must be admin to use this button')
    end
end)
:on_admin_clicked(function(event)
    -- Yes i know this can just be an if else but its an example
    game.print(event.player.name..' pressed my admin button')
end)
-- Drawing a concept
custom_button:draw(game.player.gui.left)

Elements

button The basic button element
checkbox The basic checkbox element
frame The basic frame element

Core

require_concept(concept) Loads a concept from the concepts file, used internally
get_concept(name) Gets the gui concept with this name
Prototype:change_name([new_name=self.name]) Used internally to save concept names to the core gui module
new_concept(name) Returns a new gui concept with no properties or events
clone_concept(name, new_name) Making anew concept based on the properties and drawing of another
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:change_name([new_name=self.name]) Used internally to save concept names to the core gui module
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, default[, setter_callback]) 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) 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
Prototype:define_combined_store([category_callback], sync_callback) Used to add a both instance and data stores which are linked together, new instances are synced to current value, changing one instance changes them all
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

The basic button element

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
# checkbox

The basic checkbox element

Properties / Events:
  • on_state_change : 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
  • use_radio : (boolean) setting to true will use radio buttons rather than checkboxs
# frame

The basic frame element

Properties / Events:

Core

# require_concept(concept)

Loads a concept from the concepts file, used internally

Parameters:
  • concept : (string) the name of the concept to require
Usage:
-- Load a base concept
Gui.require_concept('frame')
# get_concept(name)

Gets the gui concept with this name

Parameters:
  • name : (string) the name of the concept that you want to get
Usage:
-- Getting a gui concept
local button = Gui.get_concept('Button')
# Prototype:change_name([new_name=self.name])

Used internally to save concept names to the core gui module

Parameters:
  • new_name : (string) the new name of the concept (default: self.name)
Usage:
-- Internal Saving
-- this is never needed to be done, internal use only!
local button = Gui.get_concept('Button')
button:change_name('Not Button')
# new_concept(name)

Returns a new gui concept with no properties or events

Parameters:
  • name : (string) the name that you want this concept to have
Usage:
-- Making a new concept, see module usage
local button = Gui.new_concept('Button')
# clone_concept(name, new_name)

Making anew concept based on the properties and drawing of another

Parameters:
  • name : (string) the name of the concept that you want as the base
  • new_name : (string) the name that you want the new concept to have
Usage:
-- Making a new concept from another, see module usage
local custom_button = Gui.clone_concept('Button','CustomButton')
# 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('Button'):clone('CustomButton')
# Prototype:change_name([new_name=self.name])

Used internally to save concept names to the core gui module

Parameters:
  • new_name : (string) the new name of the concept (default: self.name)
Usage:
-- Internal Saving
-- this is never needed to be done, internal use only!
local button = Gui.get_concept('Button')
button:change_name('Not 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, default[, setter_callback])

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
  • default : (any) the default value for this property, although not strictly required is is strongly recomented
  • 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)
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)
    -- Note that element might be nil if this is the first draw function
    -- for this example we assume button was cloned from Prototype and so has no other draw functions defined
    -- this means that there is no element yet and what we return will be the first time the element is returned
    -- although not shown here you also can recive any extra arguments here from the call to draw
    if properties.type == 'button' then
        element = parent.draw{
            type = properties.type,
            name = properties.name,
            caption = properties.caption,
            tooltip = properties.tooltip
        }

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

    end

    -- We must return the element or what we want to be seen as the instance, this is so other draw functions have access to it
    -- for example if our custom button defined a draw function to change the font color to red
    return element
end)
# Prototype:draw(parent_element)

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
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
# Prototype:define_combined_store([category_callback], sync_callback)

Used to add a both instance and data stores which are linked together, new instances are synced to current value, changing one instance changes them all

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
Returns:
  • (GuiConcept) to allow chaining of functions
Usage:
-- Adding a way to sync enabled state bettween all instances, more useful for things that arnt buttons
local custom_button =
Gui.get_concept('CustomButton')
:define_combined_store(
function(element)
    return element.player_index -- The data is stored based on player id
end,
function(element,value)
    element.enabled = value -- We will use custom_button.set_data(element,value) to trigger this
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)