-- Concept Structure
+-- Root
+--> [data_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+Gui.new_concept('data_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+local caption = tostirng('data')
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, tooltip
+end)
-- Concept Structure
+-- Root
+--> [footer] - the footer frame
+-->> footer_caption - the lable with the title in it
+-->> footer_content - the area to contain butons
+Gui.new_concept('footer')
+:set_title('Example Footer')
-- Concept Structure
+-- Root
+--> [header] - the header frame
+-->> header_caption - the lable with the title in it
+-->> header_content - the area to contain butons
+Gui.new_concept('header')
+:set_title('Example Header')
-- Concept Structure
+-- Root
+--> [scroll_table] - the scroll area
+-->> table - the table area
+Gui.new_concept('scroll_table')
+:set_height(200)
+:set_column_count(2)
-- Concept Structure
+-- Root
+--> [unit_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+--> [properties.data_name..'_unit'] - the data label unit which can be updated
+Gui.new_concept('unit_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_unit('ticks')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+local caption = tostirng(data)
+ local unit = data > 1and'ticks'or'tick'
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, unit, tooltip
+end)
-- Concept Structure
+-- Root
+--> [data_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+Gui.new_concept('data_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+local caption = tostirng('data')
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, tooltip
+end)
-- Concept Structure
+-- Root
+--> [footer] - the footer frame
+-->> footer_caption - the lable with the title in it
+-->> footer_content - the area to contain butons
+Gui.new_concept('footer')
+:set_title('Example Footer')
-- Concept Structure
+-- Root
+--> [header] - the header frame
+-->> header_caption - the lable with the title in it
+-->> header_content - the area to contain butons
+Gui.new_concept('header')
+:set_title('Example Header')
-- Concept Structure
+-- Root
+--> [scroll_table] - the scroll area
+-->> table - the table area
+Gui.new_concept('scroll_table')
+:set_height(200)
+:set_column_count(2)
-- Concept Structure
+-- Root
+--> [unit_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+--> [properties.data_name..'_unit'] - the data label unit which can be updated
+Gui.new_concept('unit_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_unit('ticks')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+local caption = tostirng(data)
+ local unit = data > 1and'ticks'or'tick'
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, unit, tooltip
+end)
@@ -334,7 +335,7 @@
generated by LDoc
diff --git a/expcore/gui/concepts/label.lua b/expcore/gui/concepts/label.lua
index 1cf70eac..9c2df448 100644
--- a/expcore/gui/concepts/label.lua
+++ b/expcore/gui/concepts/label.lua
@@ -6,7 +6,7 @@
local Gui = require 'expcore.gui.core'
--[[-- A piece of text.
-@element frame
+@element label
@tparam ?string|Concepts.LocalisedString caption the caption that will show in the label
@tparam ?string|Concepts.LocalisedString description the description that will show on the label
diff --git a/expcore/gui/core.lua b/expcore/gui/core.lua
index 1edcd0b3..23b13a5b 100644
--- a/expcore/gui/core.lua
+++ b/expcore/gui/core.lua
@@ -30,7 +30,7 @@ end
Gui.require_concept('expgaming') --- @dep Gui.style.frame
]]
function Gui.require_style(style_name)
- require('expcore.gui.styles.'..style_name)
+ require('expcore.gui.styles.'..style_name..'.index')
end
--[[-- Gets a gui concept from name, id, or its self
@@ -139,6 +139,45 @@ function Gui.destroy(element)
return false
end
+--[[-- Finds and returns a gui element if it is valid from a long chain of element names or concepts
+@tparam LuaGuiElement element the root element to start checking from
+@tparam ?string|table ... element names or element concepts that point to your element
+@treturn[1] boolean if the element was found, failed
+@treturn[1] string the path of the element that the search stoped at
+@treturn[2] boolean if the element was found, found
+@treturn[2] LuaGuiElement the element that was found
+@usage-- Getting the center gui
+local exists, center = Gui.find(player,'gui','center')
+]]
+function Gui.find(element,...)
+ local path = tostring(element.name)
+ for _,next_element_name in pairs{...} do
+ if type(next_element_name) == 'table' then
+ next_element_name = next_element_name.name
+ end
+
+ element = element[next_element_name]
+ path = path..'.'..tostring(next_element_name)
+ if not Gui.valid(element) then
+ return false, path
+ end
+ end
+ return true, element
+end
+
+--[[-- Checks if a gui element exists or not, returns it if found else the path where it failed
+@see Gui.find
+@tparam LuaGuiElement element the root element to start checking from
+@tparam ?string|table ... element names or element concepts that point to your element
+@treturn[1] boolean if the element was found, failed
+@treturn[1] string the path of the element that the search stoped at
+@treturn[2] boolean if the element was found, found
+@treturn[2] LuaGuiElement the element that was found
+@usage-- Getting the center gui
+local exists, center = Gui.exists(player,'gui','center')
+]]
+Gui.exists = Gui.find
+
--[[-- Toggles the enabled state of an element
@tparam LuaGuiElement element the element that you want to toggle the enabled state of
@treturn boolean the new enabled state of the element
diff --git a/expcore/gui/prototype.lua b/expcore/gui/prototype.lua
index 902aa4dc..269b4023 100644
--- a/expcore/gui/prototype.lua
+++ b/expcore/gui/prototype.lua
@@ -417,6 +417,7 @@ end
--[[-- Calls all the draw functions in order to create this concept in game; will also store and sync the instance if stores are used
@tparam LuaGuiElement parent_element the element that the concept will use as a base
+@tparam[opt] string override_name when given this will be the name of the element rather than the concept id
@treturn 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 =
@@ -425,10 +426,12 @@ 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)
]]
-function Prototype:draw(parent_element,...)
+function Prototype:draw(parent_element,override_name,...)
+ local old_name = self.properties.name
local parent = parent_element
local element
+ if override_name then self.properties.name = override_name end
-- Loop over all the draw defines, element is updated when a value is returned
for _,draw_callback in pairs(self.draw_callbacks) do
local success, _element, _parent = pcall(draw_callback,self.properties,parent,element,...)
@@ -436,10 +439,14 @@ function Prototype:draw(parent_element,...)
if _element then element = _element end
if _parent then parent = _parent end
elseif not success then
+ self.properties.name = old_name
error('Gui draw handler error with '..self.debug_name..':\n\t'.._element)
end
end
+ -- Return the name back to its previous value
+ self.properties.name = old_name
+
-- Adds the instance if instance store is used
if self.add_instance then
self.add_instance(element)
diff --git a/expcore/gui/styles/expstyle/alignment.lua b/expcore/gui/styles/expstyle/alignment.lua
new file mode 100644
index 00000000..80c44f8a
--- /dev/null
+++ b/expcore/gui/styles/expstyle/alignment.lua
@@ -0,0 +1,49 @@
+--[[-- Core Module - ExpStyle
+ @core ExpStyle
+ @alias expstyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'flow' -- @dep gui.concept.flow
+
+--[[-- A flow which can be used to align text and other elements
+@see Gui.flow
+@element alignment
+@usage-- Concept Structure
+-- Root
+--> [alignment] - the alignment area
+Gui.new_concept('alignment')
+:set_horizontal_align('center')
+]]
+
+Gui.new_concept('flow')
+:save_as('alignment')
+
+:new_property('horizontal_align',nil,'right')
+:new_property('vertical_align',nil,'center')
+:new_property('width')
+:new_property('height')
+
+:define_draw(function(properties,parent,element)
+ local style = element.style
+ Gui.set_padding(element,1,1,2,2)
+
+ -- Set the alignment of the flow
+ style.horizontal_align = properties.horizontal_align
+ style.vertical_align = properties.vertical_align
+
+ -- Set the stretchablity based on the alignment
+ style.horizontally_stretchable = style.horizontal_align ~= 'center'
+ style.vertically_stretchable = style.vertical_align ~= 'center'
+
+ -- Set the width if given
+ local width = properties.width
+ if width then style.width = width end
+
+ -- Set the hieght if given
+ local height = properties.height
+ if height then style.height = height end
+
+ return element
+end)
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/container.lua b/expcore/gui/styles/expstyle/container.lua
new file mode 100644
index 00000000..00ac52ac
--- /dev/null
+++ b/expcore/gui/styles/expstyle/container.lua
@@ -0,0 +1,37 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'frame' -- @dep gui.concept.frame
+
+--[[-- A container frame that can be used to add a boader around your content
+@see Gui.frame
+@element container
+@usage-- Concept Structure
+-- Root
+--> [container] - the outer frame
+-->> container - the content area
+Gui.new_concept('container')
+]]
+
+Gui.new_concept('frame')
+:save_as('container')
+:define_draw(function(properties,parent,element)
+ -- Update the outter frame padding
+ element.style.padding = 2
+
+ -- Add the inner frame
+ element = element.add{
+ name = 'container',
+ type = 'frame',
+ direction = properties.direction,
+ style = 'window_content_frame_packed'
+ }
+
+ -- Update the inner frame padding
+ element.style.padding = 0
+
+ return element
+end)
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/data_label.lua b/expcore/gui/styles/expstyle/data_label.lua
new file mode 100644
index 00000000..62c39e73
--- /dev/null
+++ b/expcore/gui/styles/expstyle/data_label.lua
@@ -0,0 +1,101 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'label' -- @dep gui.concept.frame
+
+local right_align =
+Gui.new_concept('alignment')
+
+--[[-- A label pair which has a static label and a data label which can be changed
+@see Gui.label
+@element data_label
+@usage-- Concept Structure
+-- Root
+--> [data_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+Gui.new_concept('data_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+ local caption = tostirng('data')
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, tooltip
+end)
+]]
+
+local data_label =
+Gui.new_concept('label')
+:save_as('data_label')
+:new_property('data_label_name')
+:new_property('data_caption')
+:new_property('data_tooltip')
+:new_property('data_format',nil,function(concept,element,data,...)
+ return tostring(data)
+end)
+
+-- Draw
+:define_draw(function(properties,parent,element)
+ -- Make the label right aligned
+ local data_name = properties.data_label_name or properties.name..'_data'
+ local right_align_element = right_align:draw(parent,data_name)
+
+ -- Add a new label
+ local data_label_element =
+ right_align_element.add{
+ name = 'data_label'
+ }
+
+ -- Get the data caption
+ local caption = Gui.resolve_property(properties.data_caption,element)
+ if caption then
+ data_label_element.caption = caption
+ end
+
+ -- Get the data tooltip
+ local tooltip = Gui.resolve_property(properties.data_tooltip,element)
+ if tooltip then
+ data_label_element.tooltip = tooltip
+ end
+
+ return data_label_element
+end)
+
+--[[-- Updates the caption and tooltip of the data label using the data format function
+@tparam LuaGuiElement element the data label element that you want to update
+@tparam any data the data that you want to pass to the format function
+@usage-- Updating the data to the current game tick
+data_label:update_data_element(element,game.tick)
+]]
+function data_label:update_data_element(element,data,...)
+ local caption, tooltip = self.properties.data_format(self,element,data,...)
+ if caption then
+ element.caption = caption
+ end
+ if tooltip then
+ element.tooltip = tooltip
+ end
+end
+
+--[[-- Updates the caption and tooltip of the data label using the data format function, given the parent of the data label
+@tparam LuaGuiElement parent the parent element to the data label element that you want to update
+@tparam any data the data that you want to pass to the format function
+@usage-- Updating the data to the current game tick
+data_label:update_from_parent(parent,game.tick)
+]]
+function data_label:update_from_parent(parent,data,...)
+ local properties = self.properties
+ local data_name = properties.data_label_name or properties.name..'_data'
+ local element = parent[data_name] and parent[data_name].data_label or error('Data label is not a child of this element element',2)
+
+ local caption, tooltip = properties.data_format(self,element,data,...)
+ if caption then
+ element.caption = caption
+ end
+ if tooltip then
+ element.tooltip = tooltip
+ end
+end
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/footer.lua b/expcore/gui/styles/expstyle/footer.lua
new file mode 100644
index 00000000..2ca0a762
--- /dev/null
+++ b/expcore/gui/styles/expstyle/footer.lua
@@ -0,0 +1,52 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'frame' -- @dep gui.concept.table
+
+local right_align =
+Gui.new_concept('alignment')
+
+--[[-- A frame that acts as a footer to a section of content
+@see Gui.frame
+@element footer
+@tparam string tooltip the tooltip to show on the title
+@usage-- Concept Structure
+-- Root
+--> [footer] - the footer frame
+-->> footer_caption - the lable with the title in it
+-->> footer_content - the area to contain butons
+Gui.new_concept('footer')
+:set_title('Example Footer')
+]]
+
+Gui.new_concept('frame')
+:save_as('footer')
+:new_property('tooltip')
+
+-- Draw
+:define_draw(function(properties,parent,element)
+ -- Update the table style
+ Gui.set_padding(element,2,2,4,4)
+ element.style = 'subfooter_frame'
+ element.caption = nil
+
+ local style = element.style
+ style.horizontally_stretchable = true
+ style.use_header_filler = false
+
+ -- Add the caption to the frame
+ element.add{
+ type = 'label',
+ name = 'footer_caption',
+ caption = properties.title,
+ tooltip = properties.tooltip
+ }
+
+ -- Add the right align area
+ local align = right_align:draw(element,'footer_content')
+
+ return align
+end)
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/header.lua b/expcore/gui/styles/expstyle/header.lua
new file mode 100644
index 00000000..f570442e
--- /dev/null
+++ b/expcore/gui/styles/expstyle/header.lua
@@ -0,0 +1,52 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'frame' -- @dep gui.concept.table
+
+local right_align =
+Gui.new_concept('alignment')
+
+--[[-- A frame that acts as a header to a section of content
+@see Gui.frame
+@element header
+@tparam string tooltip the tooltip to show on the title
+@usage-- Concept Structure
+-- Root
+--> [header] - the header frame
+-->> header_caption - the lable with the title in it
+-->> header_content - the area to contain butons
+Gui.new_concept('header')
+:set_title('Example Header')
+]]
+
+Gui.new_concept('frame')
+:save_as('header')
+:new_property('tooltip')
+
+-- Draw
+:define_draw(function(properties,parent,element)
+ -- Update the table style
+ Gui.set_padding(element,2,2,4,4)
+ element.style = 'subheader_frame'
+ element.caption = nil
+
+ local style = element.style
+ style.horizontally_stretchable = true
+ style.use_header_filler = false
+
+ -- Add the caption to the frame
+ element.add{
+ type = 'label',
+ name = 'header_caption',
+ caption = properties.title,
+ tooltip = properties.tooltip
+ }
+
+ -- Add the right align area
+ local align = right_align:draw(element,'header_content')
+
+ return align
+end)
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/index.lua b/expcore/gui/styles/expstyle/index.lua
new file mode 100644
index 00000000..6d773cfb
--- /dev/null
+++ b/expcore/gui/styles/expstyle/index.lua
@@ -0,0 +1,28 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+ @alias expstyle
+]]
+
+--- @dep expcore.gui
+
+--- @dep gui.concept.frame
+
+--- @dep gui.concept.flow
+
+--- @dep gui.concept.table
+
+--- @dep gui.concept.scroll
+
+local function r(name)
+ require('expcore.gui.styles.expstyle.'..name)
+end
+
+r 'container'
+r 'alignment'
+r 'header'
+r 'footer'
+r 'scroll_table'
+r 'time_label'
+r 'data_label'
+r 'unit_label'
+r 'toggle_button'
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/scroll_table.lua b/expcore/gui/styles/expstyle/scroll_table.lua
new file mode 100644
index 00000000..cd48ff0a
--- /dev/null
+++ b/expcore/gui/styles/expstyle/scroll_table.lua
@@ -0,0 +1,60 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'table' -- @dep gui.concept.table
+Gui.require_concept 'scroll' -- @dep gui.concept.scroll
+
+local scroll_area =
+Gui.new_concept('scroll')
+:set_vertical_scroll('auto-and-reserve-space')
+:set_horizontal_scroll('never')
+
+--[[-- A table that is inside a vertical scroll area
+@see Gui.table
+@element scroll_table
+@tparam number hight the max hight of the scroll area
+@usage-- Concept Structure
+-- Root
+--> [scroll_table] - the scroll area
+-->> table - the table area
+Gui.new_concept('scroll_table')
+:set_height(200)
+:set_column_count(2)
+]]
+
+Gui.new_concept('table')
+:save_as('scroll_table')
+:new_property('hight',nil,100)
+
+-- Add a scroll before the table is drawn
+:define_pre_draw(function(properties,parent,element)
+ local scroll = scroll_area:draw(parent,properties.name)
+
+ -- Set the scroll style
+ Gui.set_padding(scroll,1,1,2,2)
+ scroll.style.horizontally_stretchable = true
+ scroll.style.maximal_height = properties.hight
+
+ -- Change the name of the element to table before it is drawn
+ properties.name = 'table'
+
+ return element, scroll
+end)
+
+-- Draw
+:define_draw(function(properties,parent,element)
+ -- Update the table style
+ local style = element.style
+ style.padding = 0
+ style.horizontally_stretchable = true
+ style.vertical_align = 'center'
+ style.cell_padding = 0
+
+ -- Change the stored name back to the actual name
+ properties.name = element.parent.name
+
+ return element
+end)
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/time_label.lua b/expcore/gui/styles/expstyle/time_label.lua
new file mode 100644
index 00000000..3fc4b004
--- /dev/null
+++ b/expcore/gui/styles/expstyle/time_label.lua
@@ -0,0 +1,92 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+local format_time = ext_require('expcore.common','format_time') --- @dep expcore.common
+
+--- Converts a tick into string format with workds and symbols
+local function get_format(properties,time)
+ local caption, tooltip
+
+ -- Check if a custom format is wanted
+ if properties.time_format then
+ -- Get the caption
+ local format = table.deep_copy(properties.time_format)
+ caption = format_time(time,format)
+
+ -- Get the tooltip, always long format
+ format.long = true
+ tooltip = format_time(time,format)
+
+ else
+ -- Get the caption
+ caption = format_time(time,{
+ hours = properties.use_hours,
+ minutes = true,
+ seconds = true
+ })
+
+ -- Get the tooltip, same as the caption but long format
+ tooltip = format_time(time,{
+ hours = properties.use_hours,
+ minutes = true,
+ seconds = true,
+ long = true
+ })
+
+ end
+
+ return caption, tooltip
+end
+
+--[[-- A label that show time in a nice, user friendly way
+@element time_label
+@tparam number time the time to display in tick
+@usage-- Concept Structure
+-- Root
+--> [time_label] - the label with the time
+local time_label =
+Gui.new_concept('time_label')
+:set_use_hours(true)
+:set_time(game.tick)
+
+time_label:update_time(element,game.tick)
+]]
+
+local time_label =
+Gui.new_concept()
+:save_as('time_label')
+
+-- Properties
+:new_property('time')
+:new_property('use_hours',nil,false)
+:new_property('time_format')
+
+-- Draw
+:define_draw(function(properties,parent,element,time)
+ -- Get the caption and tooltip
+ local caption, tooltip = get_format(properties,time or properties.time)
+
+ -- Draw a label
+ element = parent.add{
+ name = properties.name,
+ type = 'label',
+ caption = caption,
+ tooltip = tooltip
+ }
+
+ return element
+end)
+
+--[[-- Updates the time that is on a label
+@tparam LuaGuiElement element the label that you want to update
+@tparam number time the number of tick you want it to show
+@usage-- Update the time to show game time
+time_label:update_time(element,game.time)
+]]
+function time_label:update_time(element,time)
+ local caption, tooltip = get_format(self.properties,time)
+ element.caption = caption
+ element.tooltip = tooltip
+end
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/toggle_button.lua b/expcore/gui/styles/expstyle/toggle_button.lua
new file mode 100644
index 00000000..00a894c5
--- /dev/null
+++ b/expcore/gui/styles/expstyle/toggle_button.lua
@@ -0,0 +1,49 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'button' -- @dep gui.concept.table
+
+--[[-- A button that will toggle its caption each time it is pressed
+@see Gui.button
+@element toggle_button
+@tparam string alt_caption the caption to show on the button in its true state
+@tparam string alt_tooltip the tooltip to show on the button in its true state
+@usage-- Concept Structure
+-- Root
+--> [toggle_button] - the header button
+Gui.new_concept('toggle_button')
+:set_caption('<')
+:set_tooltip('Press to close.')
+:set_alt_caption('>')
+:set_alt_tooltip('Press to open.')
+:on_click(function(event)
+ local state = event.state and 'close' or 'open'
+ event.player.print('Toggle button is now: '..state)
+end)
+]]
+
+Gui.new_concept('button')
+:save_as('toggle_button')
+:new_property('alt_caption')
+:new_property('alt_tooltip')
+
+-- Events
+:on_click(function(event)
+ local concept = event.concept
+ local properties = concept.properties
+ local element = event.element
+ if element.caption == properties.caption then
+ element.caption = properties.alt_caption
+ element.tooltip = properties.alt_tooltip or properties.tooltip
+ event.state = true
+
+ else
+ element.caption = properties.caption
+ element.tooltip = properties.tooltip or properties.alt_tooltip
+ event.state = false
+
+ end
+end)
\ No newline at end of file
diff --git a/expcore/gui/styles/expstyle/unit_label.lua b/expcore/gui/styles/expstyle/unit_label.lua
new file mode 100644
index 00000000..50bdd4b5
--- /dev/null
+++ b/expcore/gui/styles/expstyle/unit_label.lua
@@ -0,0 +1,107 @@
+--[[-- Core Module - ExpStyle
+ @module ExpStyle
+]]
+
+local Gui = require 'expcore.gui' -- @dep expcore.gui
+
+Gui.require_concept 'label' -- @dep gui.concept.frame
+
+local right_align =
+Gui.new_concept('alignment')
+
+--[[-- A label triplet which has a static label, a data label which can be changed, and a unit label
+@see Gui.label
+@see data_label
+@element unit_label
+@usage-- Concept Structure
+-- Root
+--> [unit_label] - the static label
+--> [properties.data_name] - the data label which can be updated
+--> [properties.data_name..'_unit'] - the data label unit which can be updated
+Gui.new_concept('unit_label')
+:set_data_label_name('game_ticks')
+:set_data_caption('0')
+:set_data_unit('ticks')
+:set_data_format(function(concept,element,data,...)
+ -- This is used with update_data_element and update_from_parent
+ local caption = tostirng(data)
+ local unit = data > 1 and 'ticks' or 'tick'
+ local tooltip = 'This game has beeing running for: '..caption..' ticks'
+ return caption, unit, tooltip
+end)
+]]
+
+local unit_label =
+Gui.new_concept('data_label')
+:save_as('unit_label')
+:new_property('data_label_name')
+:new_property('data_caption')
+:new_property('data_tooltip')
+:new_property('data_unit')
+:new_property('data_format',nil,function(concept,element,data,...)
+ local base_unit = concept.properties.data_unit
+ local caption = tostring(data)
+ local unit = data == 1 and base_unit or base_unit..'s'
+ return caption, unit
+end)
+
+-- Draw
+:define_draw(function(properties,parent,element)
+ -- Get the unit data
+ local unit = Gui.resolve_property(properties.data_unit,element)
+
+ -- Add the unit label
+ parent.add{
+ name = element.name..'_unit',
+ caption = unit or '',
+ tooltip = element.tooltip
+ }
+
+ return element
+end)
+
+--[[-- Updates the caption and tooltip and unit of the data label using the data format function
+@tparam LuaGuiElement element the unit label element that you want to update
+@tparam any data the data that you want to pass to the format function
+@usage-- Updating the data to the current game tick
+unit_label:update_data_element(element,game.tick)
+]]
+function unit_label:update_data_element(element,data,...)
+ local caption, unit, tooltip = self.properties.data_format(self,element,data,...)
+ local unit_element = element.parent.parent[element.name..'_unit']
+ if caption then
+ element.caption = caption
+ end
+ if tooltip then
+ element.tooltip = tooltip
+ unit_element.tooltip = tooltip
+ end
+ if unit then
+ unit_element.caption = unit
+ end
+end
+
+--[[-- Updates the caption and tooltip and unit of the unit label using the data format function, given the parent of the unit label
+@tparam LuaGuiElement parent the parent element to the unit label element that you want to update
+@tparam any data the data that you want to pass to the format function
+@usage-- Updating the data to the current game tick
+unit_label:update_from_parent(parent,game.tick)
+]]
+function unit_label:update_from_parent(parent,data,...)
+ local properties = self.properties
+ local data_name = properties.data_label_name or properties.name..'_data'
+ local element = parent[data_name] and parent[data_name].data_label or error('Data label is not a child of this element element',2)
+ local unit_element = parent[data_name..'_unit']
+
+ local caption, unit, tooltip = properties.data_format(self,element,data,...)
+ if caption then
+ element.caption = caption
+ end
+ if tooltip then
+ element.tooltip = tooltip
+ unit_element.tooltip = tooltip
+ end
+ if unit then
+ unit_element.caption = unit
+ end
+end
\ No newline at end of file