mtimer/system/formspec_helpers.lua
2021-05-15 17:06:41 +02:00

274 lines
11 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local m = mtimer
local S = m.translator
local esc = minetest.formspec_escape
-- Get a table line
--
-- The index determines the position from top within the current container and
-- is calculated to display the string in the correct position.
--
-- If `name` is a literal `'-'` then a line is printed at the position.
--
-- @param index The numerical index for the line
-- @param name Human-readable name for the variable
-- @param variable The variable like its used in the definition
-- @param value The value to show for that variable
-- @return string The created formspec string
mtimer.get_table_line = function (index, name, variable, value)
local position = ((index-1) * 0.4)
if name == '-' then
return 'box[0,'..position..';+contentWidth,0.02;#ffffff]'
end
return table.concat({
'label[0,'..position..';'..name..']',
'label[4,'..position..';'..variable..']',
'label[7,'..position..';'..value..']'
}, ' ')
end
-- Get a button with icon
--
-- This function returns a fully formatted button with icon.
--
-- The provided ID is set as the buttons ID as well as the buttons image.
-- When set as image all colons are replaced with underscores and the id then
-- is formatted: `mtimer_ID.png` where `ID` is the given ID.
--
-- The definition table sets up the buttons parameters and is fully optional
-- even if it makes no sense.
--
-- definition = {
-- label = 'My Cool Button label' or '',
-- width = 5, or 3,
-- image_size = 1, or 0.5,
-- colorize = color_table or { use = false },
-- container = { left = 1, top = 1} or pos_container
-- exit_button = true or false
-- }
--
-- The container table is used to position the button. If the `container` sub
-- table is unset, the following table is used, causing the button to be in the
-- top left corner of the formspec if not contained in another container.
--
-- pos_container = {
-- left = 0,
-- top = 0
-- }
--
-- Via the `colorize` sub-table it is possible to add colorization to the icon
-- shown oin the button. The table contains two entries to define the color and
-- the ratio for applying the color.
--
-- color_table = {
-- color = '#729fcf',
-- ratio = 200
-- }
--
-- If one of the values is omitted the value shown in the example is used.
--
-- @param id The ID for the button
-- @param definition The definition table as described
-- @return string The created button as formspec code
mtimer.get_icon_button = function (id, definition)
local def = definition or {}
-- Define colorization of button texture
local t_table = type(def.colorize) == 'table'
local t_values = t_table and def.colorize or { use = false }
local t_color = t_values.color or '#729fcf'
local t_ratio = t_values.ratio or 200
local t_colorize = '^[colorize:'..t_color..':'..t_ratio
-- Set button defaults
local b_width = def.width or 3
local i_size = def.image_size or 0.5
local c_left = (def.container or {}).left or 0
local c_top = (def.container or {}).top or 0
-- Calculate button parameters
local b_padding = i_size / 4
local b_height = (b_padding * 2) + i_size
local l_top_pos = i_size / 2
local l_left_pos = i_size + (i_size / 4)
-- Create/Return the button
return (table.concat({
'container[+containerLeft,+containerTop]',
' container[+buttonPadding,+buttonPadding]',
' image[0,0;+imageSize,+imageSize;+icon+colorize]',
' label[+labelLeftPos,+labelTopPos;+label]',
' container_end[]',
' +buttonType[0,0;+buttonWidth,+buttonHeight;+id;]',
'container_end[]'
}, ' '):gsub('%+%w+', {
['+containerLeft'] = c_left,
['+containerTop'] = c_top,
['+buttonType'] = def.exit_button==true and 'button_exit' or 'button',
['+buttonWidth'] = b_width,
['+buttonHeight'] = b_height,
['+buttonPadding'] = b_padding,
['+imageSize'] = i_size,
['+icon'] = 'mtimer_'..id:gsub(':', '_')..'.png',
['+colorize'] = t_values.use == false and '' or t_colorize,
['+labelLeftPos'] = l_left_pos,
['+labelTopPos'] = l_top_pos,
['+id'] = id,
['+label'] = esc(def.label or '')
}))
end
-- Build the formspec frame
--
-- This function builds and displays a formspec based on the input.
--
-- The `id` is the usual formspec ID (for example `mymod:my_formspec`) and
-- has to be provided as a simple string all other parameters are provided via
-- the `def` table. The following table is an example.
--
-- {
-- title = 'Nice Title' -- Automatically prefixed for orientation
-- prefix = '[Blarb] ' -- Optional title prefix
-- width = 8, -- Optional width of the content container
-- height = 3, -- Optional height of the content container
-- show_to = 'Playername', -- Name of the player to show the formspec to
-- hide_buttons = true, -- Optionally hide buttons
-- hide_title = true, -- Optionally hide title
-- icon_size = 0.5, -- Optionally set title icon size
-- content_offset = 0, -- Optionally Offset content height position
-- formspec = {} -- Table with formspec definition
-- }
--
-- When set the title is prefixed with the prefix value. If omitted “[mTimer] ”
-- is used. The example creates “[Blarb] Nice Title” as title. Translated
-- strings can be used here. The Title and prefix are “formspec-safe” so
-- strings that are formspec elements can be used to show them literal.
--
-- The default buttons can be hidden by adding `hide_buttons = true` to the
-- definition table. If omitted the buttons are shown. When not shown the
-- formspec size will be reduced by the amout of units the buttons would
-- have taken place. Same for the title with `hide_title = true`.
--
-- Some formspec elements do not properly start at 0,0 even if set so. The
-- `content_offset` attribute offsets the content vertically by the given
-- amount of units. Formspec height and button positions are adapted to the
-- given value.
--
-- The table entries for `formspec` are the usual formspec elements that
-- define what a formspec looks like. You can write all definition in one entry
-- or split the definition into multiple entries.
--
-- The definition defines the CONTENT of the formspec not the whole formspec so
-- you can easily start at 0,0 for your definition. The function automatically
-- places everything in relation to the formspec frame and default buttons.
--
-- The minimum formspec width and height are 10 units in width and 5 units in
-- height. So `width` and `height` can be omitted when all of your content fits
-- into the default size.
--
-- All formspec table entries can contain the following variables. Variables
-- start with a plus sign (+) and are read until any character that is not
-- a letter. Some variables are useless, some can be used quite well.
--
-- Variable Name Value Type
-- --------------------------------------------------------------------------
-- +width Width of the formspec
-- +height Height of the formspec
-- +iconSize Size of the title icon
-- +labelPositionLeft Position of the title label from left side
-- +labelPositionTop Position of the title label from top
-- +linePosition Position of the title separator line
-- +titleText The text of the title label (the dialog title)
-- +titleIcon The icon that is used in the dialog title
-- +contentPosition Position of the actual content of the dialog
-- +buttonsPosition The position where the buttons are
--
-- @param id The ID of the formspec
-- @param def The definition table as described
-- @return string the constructed “frame”
mtimer.show_formspec = function (id, def)
local title_text = def.title or ''
local title_prefix = def.prefix or '[mTimer] '
local content_offset = def.content_offset or 0
local width = (def.width or 0) <= 10 and 10 or def.width
local height = ((def.height or 0) <= 4 and 5 or def.height)+content_offset
local icon_size = def.icon_size or 0.5
local line_position = 0
local buttons = ''
local title = ''
-- Set up title
if def.hide_title ~= true then
line_position = icon_size + 0.25
content_offset = content_offset + line_position + (icon_size / 2) + 0.1
height = height + content_offset + (icon_size / 2)
title = table.concat({
'container[0.25,0.25]',
' image[0,0;+iconSize,+iconSize;+titleIcon]',
' label[+labelPositionLeft,+labelPositionTop;+titleText]',
' box[0,+linePosition;+contentWidth,0.04;#ffffff]',
'container_end[]'
}, ' ')
end
-- Set up buttons
if def.hide_buttons ~= true then
height = height + 1
buttons = table.concat({
'container[0.25,+buttonsPosition]',
'box[0,0;+contentWidth,0.04;#ffffff]',
mtimer.get_icon_button('main_menu', {
label = S('Main Menu'),
width = 2.5, container = { top = 0.25 }
}),
'container[+contentWidth,0.25]',
mtimer.get_icon_button('exit', {
label = S('Exit'),
exit_button = true,
width = 2.5,
container = { left = -2.5 }
}),
mtimer.get_icon_button('default', {
label = S('Default'),
width = 2.5,
container = { left = -5.25 }
}),
'container_end[]', -- right side buttons
'container_end[]' -- buttons
}, ' ')
end
-- Build formspec
local formspec = table.concat({
'formspec_version[2]',
'size[+width,+height]',
title,
'container[0.25,+contentPosition]',
table.concat(def.formspec, ' '),
'container_end[]',
buttons
}, ' '):gsub('%+%a+', {
-- Formspec frame
['+width'] = width + 0.5,
['+height'] = height + 0.5,
['+contentWidth'] = width,
['+contentPosition'] = content_offset + 0.25,
['+iconSize'] = icon_size,
-- Title-related settings
['+labelPositionLeft'] = icon_size + (icon_size / 4),
['+labelPositionTop'] = (icon_size / 2),
['+linePosition'] = line_position,
['+titleText'] = minetest.formspec_escape(title_prefix..title_text),
['+titleIcon'] = 'mtimer_'..id:gsub('mtimer:', '')..'.png',
-- Buttons-related settings
['+buttonsPosition'] = height - 0.75,
})
-- Show formspec to the plauyer
minetest.show_formspec(def.show_to, id, formspec)
end