<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=White+haired+uncle</id>
	<title>The Battle for Wesnoth Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.wesnoth.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=White+haired+uncle"/>
	<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/Special:Contributions/White_haired_uncle"/>
	<updated>2026-04-25T17:24:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/wesnoth/map&amp;diff=74004</id>
		<title>LuaAPI/wesnoth/map</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/wesnoth/map&amp;diff=74004"/>
		<updated>2024-11-23T18:31:45Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* wesnoth.map.get_cubic */  minor typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|11}}&lt;br /&gt;
&lt;br /&gt;
This module contains functions for working with the game map. Some of the functions can be called as methods of the map itself. In 1.15.11, there exists only one map in the game context, which can be accessed as [[LuaAPI/types/map|'''wesnoth.current.map''']], while in the map generation context, a map can be created with [[#wesnoth.map.create]] or [[#wesnoth.map.generate]]. In future, it may become possible to create maps on the fly or read them from disk.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.find ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.find'''(''filter config'') &amp;amp;rarr; ''list of hex references''&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.find'''(''filter config'', [''reference_unit'']) &amp;amp;rarr; ''list of hex references''&lt;br /&gt;
* {{LuaMapOnly}} '''wesnoth.map.find'''(''map'', ''filter userdata'', [''list of locations'']) &amp;amp;rarr; ''list of locations''&lt;br /&gt;
* {{LuaMapOnly}} '''wesnoth.map.find_in_radius'''(''map'', ''center'', ''radius'', ''filter userdata'') &amp;amp;rarr; ''list of locations''&lt;br /&gt;
&lt;br /&gt;
Returns a table containing all the locations matching the given filter. Locations are stored as a ''hex reference'' which has x and y keys along with a variety of other functions. See [[StandardLocationFilter]] for details about location filters. If a unit is passed, it can be referenced from the filter via the $teleport_unit variable, as well as in WFL formulas used in the filter.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' In older versions of Wesnoth, locations returned from a filter were stored as simple pairs, &amp;lt;syntaxhighlight lang=lua inline&amp;gt;{x,y}&amp;lt;/syntaxhighlight&amp;gt;. For compatibility purposes, accessing a location this way (as &amp;lt;syntaxhighlight lang=lua inline&amp;gt;loc[1]&amp;lt;/syntaxhighlight&amp;gt; and &amp;lt;syntaxhighlight lang=lua inline&amp;gt;loc[2]&amp;lt;/syntaxhighlight&amp;gt;) is still supported.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
-- replace all grass terrains by roads&lt;br /&gt;
for i,loc in ipairs(wesnoth.map.find{terrain = &amp;quot;Gg&amp;quot;}) do&lt;br /&gt;
    wesnoth.current.map[loc] = &amp;quot;Rr&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The mapgen form of this function uses a different format for the filter which is somewhat experimental. An example of its use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local map = wesnoth.map.create(18,18,&amp;quot;Gg&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
-- Assume there is some generation code here, so the map is no longer just grass&lt;br /&gt;
&lt;br /&gt;
local F, f = wesnoth.map.filter, wesnoth.map.filter_tags&lt;br /&gt;
&lt;br /&gt;
-- Find all elvish villages&lt;br /&gt;
local elf_villages = map:find(F(f.terrain('*^Ve')))&lt;br /&gt;
&lt;br /&gt;
-- Find all great trees within 7 tiles of an elvish keep&lt;br /&gt;
local elf_keeps = map:find(F(f.terrain('Kv')))&lt;br /&gt;
local nearby_trees = map:find_in_radius(elf_keeps, 7, F(f.terrain('*^Fet')))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Possible filter tags for this function are: terrain, all, any, none, notall, adjacent, find_in, radius, x, y, is_loc, formula.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.get'''(''location'') &amp;amp;rarr; ''hex reference''&lt;br /&gt;
&lt;br /&gt;
Constructs a [[LuaAPI/types/hex|''hex reference'']] for the specified location.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.matches ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.matches'''(''location'', ''filter config'', [''reference_unit'']) &amp;amp;rarr; ''boolean''&lt;br /&gt;
* {{LuaGameOnly}} ''hex'':'''matches'''(''filter config'', [''reference_unit'']) &amp;amp;rarr; ''boolean''&lt;br /&gt;
* {{LuaMapOnly}} ''map'':'''matches'''(''location'', ''filter userdata'') &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Returns true if the given location passes the filter. The location can be passed either as two separate x and y parameters or as an object with x and y keys (such as a hex reference or a unit). If a ''reference_unit'' is passed, it can be referenced from the filter via the $teleport_unit variable, as well as in WFL formulas used in the filter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local b = wesnoth.map.matches(x, y, {&lt;br /&gt;
    terrain = &amp;quot;Ww&amp;quot;,&lt;br /&gt;
    wml.tag.filter_adjacent_location{terrain = &amp;quot;Ds,*^Bw*&amp;quot;}&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.on_board ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} '''wesnoth.map.on_board'''(''map'', ''location'', [''include border?'']) &amp;amp;rarr; ''boolean''&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} ''map'':'''on_board'''(''location'', [''include border?'']) &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Tests if the specified location is on the map. The final parameter determines whether to count the inaccessible map border tiles as being on the map. It defaults to false.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.on_border ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} '''wesnoth.map.on_border'''(''map'', ''location'') &amp;amp;rarr; ''boolean''&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} ''map'':'''on_border'''(''location'') &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Tests if the specified location is on the map's border.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.iter ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} '''wesnoth.map.iter'''(''map'', [''include border?'']) &amp;amp;rarr; ''iterator'' &amp;amp;rArr; ''x'', ''y'', ''terrain code''&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} ''map'':'''iter'''([''include border?'') &amp;amp;rarr; ''iterator'' &amp;amp;rArr; ''x'', ''y'', ''terrain code''&lt;br /&gt;
&lt;br /&gt;
Iterate over the entire map, possibly excluding the border tiles. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
for x, y in wesnoth.current.map:iter() do&lt;br /&gt;
    wesnoth.map.add_label{x=x, y=y, text=string.format(&amp;quot;%d,%d&amp;quot;, x, y)}&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.iter_adjacent ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} '''wesnoth.map.iter_adjacent'''(''map'', ''location'', [''include border?'']) &amp;amp;rarr; ''iterator'' &amp;amp;rArr; ''x'', ''y''&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} ''map'':'''iter_adjacent'''(''location'', [''include border?'']) &amp;amp;rarr; ''iterator'' &amp;amp;rArr; ''x'', ''y''&lt;br /&gt;
&lt;br /&gt;
Iterate over the hexes adjacent to the location, excluding border tiles (unless explicitly enabled).&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.read_location ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.read_location'''(...) &amp;amp;rarr; ''location or nil'', ''number of arguments processed''&lt;br /&gt;
&lt;br /&gt;
Extracts a location from the front of a variadic parameter list. The purpose of this is to make it easy for custom user-defined functions to handle locations in the same way as the built-in API functions do. It returns the location (if it was able to find one) and the number of arguments processed, which can be:&lt;br /&gt;
&lt;br /&gt;
* 0 if nothing resembling a location was found.&lt;br /&gt;
* 1 if a location-like object was found. A location-like object can be either an array of two integers ''or'' an object that has numeric x and y keys. Note that a unit userdata satisfies the second criteria, so if a unit is found, its location will be returned.&lt;br /&gt;
* 2 if the first two arguments in the list were integers. In this case, they will be taken as the x and y coordinates.&lt;br /&gt;
&lt;br /&gt;
==== Usage example ====&lt;br /&gt;
&lt;br /&gt;
Imagine a function foo with the following signature:&lt;br /&gt;
&lt;br /&gt;
* '''foo'''(''bar : string'', [''home : location''], ''mode : string'', [''target : location''], ''moo : boolean'') &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Using read_location it could be implemented as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function foo(...)&lt;br /&gt;
	-- First argument goes in bar&lt;br /&gt;
	local bar = ...&lt;br /&gt;
	-- Read location starting at the second argument&lt;br /&gt;
	local home, n = wesnoth.map.read_location(select(2, ...))&lt;br /&gt;
	-- note: n will be 0 if a location wasn't found at that position&lt;br /&gt;
	-- This could be an error, or it could be handled as an optional parameter&lt;br /&gt;
	-- Next argument after that goes in mode&lt;br /&gt;
	local mode = select(n + 2, ...)&lt;br /&gt;
	-- Then read a location into target&lt;br /&gt;
	local target, m = wesnoth.map.read_location(select(n + 2, ...))&lt;br /&gt;
	-- Finally, read a parameter into moo&lt;br /&gt;
	local moo = select(m + n + 2, ...)&lt;br /&gt;
	-- Do stuff with all these parameters&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With that code, all the following invocations of foo work:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
foo('a', 'b', true) -- both optional locations omitted&lt;br /&gt;
foo('a', 1, 2, 'q', 5, 6, false) -- locations given as separate integer parameters&lt;br /&gt;
foo('a', 'm', {1, 7},  true) -- first location omitted, second given as 2-element array&lt;br /&gt;
foo('a', some_unit, 'z', {x = 5, y = 10}, false) -- a unit also functions as a location&lt;br /&gt;
foo('a', 7, 12, 'q', my_leader, true) -- mixing different forms also works&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.split_terrain_code ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.split_terrain_code'''(''code'') &amp;amp;rarr; ''base'', ''overlay''&lt;br /&gt;
&lt;br /&gt;
Splits a terrain code into a base and an overlay. If the terrain code did not contain a &amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt;, then the ''overlay'' will be nil. The returned ''overlay'' or ''base'' can be an empty string if the code begins or ends with a &amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt;, respectively. Splitting the string &amp;lt;tt&amp;gt;'^'&amp;lt;/tt&amp;gt; will result in two empty strings.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.make_bitmap ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.make_bitmap'''(''array of locations'') &amp;amp;rarr; ''shroud data bitmap''&lt;br /&gt;
&lt;br /&gt;
Constructs a shroud data string such that the locations in the array are unshrouded and all other locations are shrouded. The string will be the minimum size required to fit all the locations.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.parse_bitmap ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.parse_bitmap'''(''shroud data bitmap'') &amp;amp;rarr; ''array of locations''&lt;br /&gt;
&lt;br /&gt;
Parses a shroud data string and returns a list of the locations that are unshrouded.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.terrain_mask ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} '''wesnoth.map.terrain_mask'''(''map'', ''pivot'', ''mask'', [''options''])&lt;br /&gt;
* {{LuaGameOnly}}{{LuaMapOnly}} ''map'':'''terrain_mask'''(''pivot'', ''mask'', [''options''])&lt;br /&gt;
&lt;br /&gt;
Overlays a terrain mask on the map. Possible options:&lt;br /&gt;
&lt;br /&gt;
* ''is_odd'' - if true, then the mask is interpreted as if it was cut out from an odd map location.&lt;br /&gt;
* ''ignore_special_locations'' - if true, then special locations on the mask won't be added to the map.&lt;br /&gt;
* ''rules'' - an array of rules. See [[TerrainMaskWML]] for the rule format. This is an array of tables, each of which has the content of a [rule] tag.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.add_label ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.add_label'''(''options'')&lt;br /&gt;
&lt;br /&gt;
Adds a label to the map. Takes the same options as the [[InterfaceActionsWML#.5Blabel.5D|[label]]] WML tag.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.remove_label ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.remove_label'''(''location'')&lt;br /&gt;
&lt;br /&gt;
Removes a label from the map. Normally this removes a global label, but you can also remove team labels with an extra '''team_name''' parameter, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
-- Removes the label on (3,12) owned by team 'rebels'&lt;br /&gt;
wesnoth.map.remove_label{x = 3, y = 12, team_name = 'rebels'}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_label ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.get_label'''(''location'', [''side or team_name'']) &amp;amp;rarr; ''label info''&lt;br /&gt;
&lt;br /&gt;
Get the full label info for a label on the specified location. With one argument, it returns a global label; otherwise, it returns a label belonging to the specified team. Passing a side (either a side number or a side userdata) uses that side's team. The returned table contains all the possible options that can be passed to '''add_label'''.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.place_area ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.place_area'''(''filter'')&lt;br /&gt;
&lt;br /&gt;
Add a new named area to the map. The filter is a [[StandardLocationFilter]], but it can also contain an '''id''' key and '''[time]''' tags. In order to remove the area later, an '''id''' must be provided. An area with no '''[time]''' tags does not affect the schedule.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.remove_area ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.remove_area'''(''id'')&lt;br /&gt;
&lt;br /&gt;
Remove the area with the given ID.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_area ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.get_area'''(''id or location'') &amp;amp;rarr; ''area schedule''&lt;br /&gt;
&lt;br /&gt;
Get the named area with the specified ID, or the area that is active on the specified location (if any). This will return nil if no area is found in either case.&lt;br /&gt;
&lt;br /&gt;
The returned object is a userdata object similar to [[LuaAPI/wesnoth#wesnoth.current|wesnoth.current.schedule]], with the following differences:&lt;br /&gt;
&lt;br /&gt;
* ''schedule''.'''liminal_bonus''' &amp;amp;rarr; nil&lt;br /&gt;
&lt;br /&gt;
This key is not supported on area schedules.&lt;br /&gt;
&lt;br /&gt;
* ''schedule''.'''id''' &amp;amp;harr; ''id''&lt;br /&gt;
&lt;br /&gt;
Check or alter the ID of the named area.&lt;br /&gt;
&lt;br /&gt;
* ''schedule''.'''hexes''' &amp;amp;harr; ''array of locations''&lt;br /&gt;
&lt;br /&gt;
Get the list of locations the area affects, or assign a new list of locations. The list may be empty, in which case the area has no effect on time of day and cannot be matched by a location filter.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.set_owner ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.set_owner'''(''location'', ''side number'')&lt;br /&gt;
&lt;br /&gt;
Set the owner of a village hex. If the specified hex is not a village, this has no effect. Set the owner to 0 to leave it owned by no-one.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_owner ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.map.get_owner'''(''location'') &amp;amp;rarr; ''side number''&lt;br /&gt;
&lt;br /&gt;
Get the owner of a village hex. If the specified hex is not a village, or if it is an unclaimed village, this returns 0.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.create ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaMapOnly}} '''wesnoth.map.create'''(''width'', ''height'', ''terrain'') &amp;amp;rarr; ''map''&lt;br /&gt;
* {{LuaMapOnly}} '''wesnoth.map.create'''(''map data string'') &amp;amp;rarr; ''map''&lt;br /&gt;
&lt;br /&gt;
Create a new map, either filled with a given terrain or read from a string.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.generate ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaMapOnly}} '''wesnoth.map.generate'''(''width'', ''height'', ''options'') &amp;amp;rarr; ''map''&lt;br /&gt;
&lt;br /&gt;
Generate a map using the [[MapGeneratorWML#The_Default_Generator|default generator]]. The following options are supported:&lt;br /&gt;
&lt;br /&gt;
* '''nplayers'''&lt;br /&gt;
* '''nvillages'''&lt;br /&gt;
* '''iterations'''&lt;br /&gt;
* '''hill_size'''&lt;br /&gt;
* '''castle_size'''&lt;br /&gt;
* '''island_size'''&lt;br /&gt;
* '''island_off_center'''&lt;br /&gt;
* '''max_lakes'''&lt;br /&gt;
* '''link_castles'''&lt;br /&gt;
* '''seed'''&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.generate_height_map ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaMapOnly}} '''wesnoth.map.generate_height_map'''(''width'', ''height'', ''options'') &amp;amp;rarr; ''array of heights''&lt;br /&gt;
&lt;br /&gt;
Generates a height map such as that used by the [[MapGeneratorWML#The_Default_Generator|default generator]]. The following options are supported:&lt;br /&gt;
&lt;br /&gt;
* '''iterations'''&lt;br /&gt;
* '''hill_size'''&lt;br /&gt;
* '''island_size'''&lt;br /&gt;
* '''center_x'''&lt;br /&gt;
* '''center_y'''&lt;br /&gt;
* '''flip_format'''&lt;br /&gt;
* '''seed'''&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_direction ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.get_direction'''(''from'', ''dir'', [''steps'']) &amp;amp;rarr; ''location''&lt;br /&gt;
&lt;br /&gt;
Calculates the hex reached by travelling in the specified direction, which should be a string such as &amp;quot;ne&amp;quot; or &amp;quot;s&amp;quot;. It will also honor direction modifiers (the prefix &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; and postfix &amp;lt;tt&amp;gt;:cw&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;:ccw&amp;lt;/tt&amp;gt;). The optional third parameter ''steps'' is number of steps to travel in specified direction. Negative ''steps'' is supported to travel in the opposite direction.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_relative_dir ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.get_relative_dir'''(''from'', ''to'') &amp;amp;rarr; ''direction''&lt;br /&gt;
&lt;br /&gt;
Calculates the direction from one hex to another. Possible returns are strings &amp;quot;n&amp;quot;, &amp;quot;ne&amp;quot;, &amp;quot;nw&amp;quot;, &amp;quot;s&amp;quot;, &amp;quot;se&amp;quot;, &amp;quot;sw&amp;quot; or &amp;quot;&amp;quot;. The empty string means no direction, which happens if ''from'' and ''to'' are same.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.rotate_right_around_center ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.rotate_right_around_center'''(''loc'', ''center'', ''angle'') &amp;amp;rarr; ''location''&lt;br /&gt;
&lt;br /&gt;
Calculates the hex obtained from rotating the specified location around the specified center by the specified angle. The angle is an integer in the range 1..6.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_adjacent_hexes ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.get_adjacent_hexes'''(''loc'') &amp;amp;rarr; ''n'', ''ne'', ''se'', ''s'', ''sw'', ''nw''&lt;br /&gt;
&lt;br /&gt;
Return all hexes adjacent to the specified hex, as six separate return values. This doesn't check whether the hexes are on the map.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local a, b, c, d, e, f = wesnoth.map.get_adjacent_hexes(3, 3)&lt;br /&gt;
local a_x = a[1]&lt;br /&gt;
local a_y = a[2]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_hexes_in_radius ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.get_hexes_in_radius'''(''center'', ''radius'') &amp;amp;rarr; ''list of locations''&lt;br /&gt;
&lt;br /&gt;
Return all hexes within the given radius, as an array of pairs. This doesn't check whether the hexes are on the map.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_hexes_at_radius ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.19|4}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.get_hexes_at_radius'''(''center'', ''radius'') &amp;amp;rarr; ''list of locations''&lt;br /&gt;
&lt;br /&gt;
Returns all hexes at exactly the given radius from the center, as an array of pairs. This doesn't check whether the hexes are on the map.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.are_hexes_adjacent ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.are_hexes_adjacent'''(''loc1'', ''loc2'') &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Tests if two hexes are adjacent.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.distance_between ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.distance_between'''(''loc1'', ''loc2'') &amp;amp;rarr; ''integer''&lt;br /&gt;
&lt;br /&gt;
Calculates the distance between two hexes. The distance is the number of hexes you would need to travel across to get from the start point to the end point.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local my_distance = wesnoth.map.distance_between({10, 10}, {20, 20})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.hex_vector_sum ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.19|4}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.hex_vector_sum'''(''loc1'', ''loc2'') &amp;amp;rarr; ''new loc''&lt;br /&gt;
&lt;br /&gt;
Treats the two locations as position vectors on the hexagonal map and adds them together.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.hex_vector_diff ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.19|4}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.hex_vector_diff'''(''loc1'', ''loc2'') &amp;amp;rarr; ''new loc''&lt;br /&gt;
&lt;br /&gt;
Treats the two locations as position vectors on the hexagonal map and takes the difference.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.hex_vector_negation ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.19|4}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.hex_vector_negation'''(''loc'') &amp;amp;rarr; ''new loc''&lt;br /&gt;
&lt;br /&gt;
Treats the location as a position vector on the hexagonal map and reverses the direction.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.get_cubic ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.19|4}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.get_cubic'''(''loc'') &amp;amp;rarr; ''cubic loc''&lt;br /&gt;
&lt;br /&gt;
Converts hex grid coordinates to [https://www.redblobgames.com/grids/hexagons/#coordinates-cube cubic hex coordinates]. This may make some algorithms easier.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map.from_cubic ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.19|4}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.map.from_cubic'''(''cubic loc'') &amp;amp;rarr; ''loc''&lt;br /&gt;
&lt;br /&gt;
Converts cubic hex coordinates back to hex grid coordinates.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=DirectActionsWML&amp;diff=73986</id>
		<title>DirectActionsWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=DirectActionsWML&amp;diff=73986"/>
		<updated>2024-11-13T20:44:16Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* [modify_unit] */  - correct description of hitpoints example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WML Tags}}&lt;br /&gt;
== Direct actions ==&lt;br /&gt;
&lt;br /&gt;
Direct actions are actions that have a direct effect on gameplay. They can be used inside of [[EventWML|events]].&lt;br /&gt;
&lt;br /&gt;
The following tags are actions:&lt;br /&gt;
&lt;br /&gt;
=== [endlevel] ===&lt;br /&gt;
Ends the scenario.&lt;br /&gt;
* '''result''': before the scenario is over, all events with ''name=result'' are triggered. If ''result=victory'', the player progresses to the next level (i.e., the next scenario in single player); if ''result=defeat'', the game returns to the main menu. &lt;br /&gt;
&lt;br /&gt;
When the result is &amp;quot;victory&amp;quot; the following keys can be used:&lt;br /&gt;
* '''bonus''': whether the player should get bonus gold (maximum possible gold that could have been earned by waiting the level out). The default is bonus=yes. {{DevFeature1.13|2}} Alternatively, a number, defining the bonus multiple (1.0 meaning full).&lt;br /&gt;
* '''carryover_report''': whether the player should receive a summary of the scenario outcome, the default is carryover_report=yes.&lt;br /&gt;
* '''save''': whether a start-of-scenario save should be created for the next scenario, the default is save=yes. Do not confuse this with saving of replays for the current scenario.&lt;br /&gt;
* '''replay_save''': whether a replay save for the current scenario is allowed, the default is replay_save=yes. If yes, the player's settings in preferences will be used to determine if a replay is saved. If no, will override and not save a replay.&lt;br /&gt;
* '''linger_mode''': If ...=yes, the screen is greyed out and there's the possibility to save before advancing to the next scenario, the default is linger_mode=yes.&lt;br /&gt;
* '''reveal_map''': (Multiplayer only) (Default is 'yes') If 'no', shroud doesn't disappear when game ended.&lt;br /&gt;
* '''next_scenario''': (default specified in '''[scenario]''' tag) the ID of the next scenario that should be played.  All units that side 1 controls at this point become available for recall in ''next_scenario''.&lt;br /&gt;
* '''carryover_percentage''': by default 80% of the gold is carried over to the next scenario, with this key the amount can be changed.&lt;br /&gt;
* '''carryover_add''': if yes the gold will be added to the starting gold the next scenario, if no the next scenario will start with the amount of the current scenario (after taxes) or the minimum in the next scenario. Default is no.&lt;br /&gt;
* '''music''': (default specified in '''[scenario]''' or '''[game_config]''' tags) a comma-separated list of music tracks from which one will be chosen and played once after any events related to the end of level result are executed; by default, victory_music is used on victory, and defeat_music on defeat.&lt;br /&gt;
* '''end_credits''': Whether to display the credits screen at the end of a single-player campaign. Defaults to ''yes''. Note that this has cumulative effects over the campaign - it persists even if the endlevel does not trigger the end of the campaign. See also [[CampaignWML]].&lt;br /&gt;
* '''end_text''': (translatable) Text that is shown centered in a black screen at the end of a campaign. Defaults to &amp;quot;The End&amp;quot;. Note that this has cumulative effects over the campaign - it persists even if the endlevel does not trigger the end of the campaign. See also [[CampaignWML]].&lt;br /&gt;
* '''end_text_duration''': Delay, in milliseconds, before displaying the game credits at the end of a campaign. In other words, for how much time '''end_text''' is displayed on screen. Defaults to 3500. Note that this has cumulative effects over the campaign - it persists even if the endlevel does not trigger the end of the campaign. See also [[CampaignWML]].&lt;br /&gt;
* &amp;lt;strike&amp;gt;'''[next_scenario_settings]''': Any tags or attribute children of this optional argument to [endlevel] are merged into the scenario/multiplayer tag of the *next* scenario. This allows you to e.g. reconfigure the [side] tags or settings, just before load. &amp;lt;/strike&amp;gt; This feature was removed in 1.11.17, it might be redesigned and reintroduced.&lt;br /&gt;
* &amp;lt;strike&amp;gt;'''[next_scenario_append]''': Any tags of this optional argument are appended at high level to the next scenario. This is most appropriate for [event] tags, although you may find other uses. Example test scenario for these features: https://gna.org/support/download.php?file_id=20119 &amp;lt;/strike&amp;gt; This feature was removed in 1.11.17, it might be redesigned and reintroduced.&lt;br /&gt;
* '''[result]''' {{DevFeature1.13|0}} Allows specification of a side specific result, this is for competitive multiplayer scenarios/campaigns where it might happen that one player wins but another player loses.  The following attributes are accepted and have the same effect as in '''[endlevel]''':&lt;br /&gt;
** '''result'''&lt;br /&gt;
** '''bonus'''&lt;br /&gt;
** '''carryover_percentage'''&lt;br /&gt;
** '''carryover_add'''&lt;br /&gt;
&lt;br /&gt;
And there is also&lt;br /&gt;
** '''side''' The number of the side for which these results should apply.&lt;br /&gt;
&lt;br /&gt;
=== [unit] ===&lt;br /&gt;
Creates a unit (either on the map, on a recall list, or into a variable for later use.)  For syntax see [[SingleUnitWML]].&lt;br /&gt;
* {{Short Note:Predefined Macro|GENERIC_UNIT}}&lt;br /&gt;
&lt;br /&gt;
This tag can also recall an existing unit, which happens when:&lt;br /&gt;
* the '''id=''' attribute is used&lt;br /&gt;
* a unit with that '''id=''' already exists&lt;br /&gt;
* (might be unnecessary) the existing unit is on the side's recall list&lt;br /&gt;
in this case, the unit is recalled at the '''x,y=''' or '''location_id=''' given, and any other data in the tag is ignored.&lt;br /&gt;
&lt;br /&gt;
Campaign authors: a usual way to recall plot-necessary heroes is to use a macro with the data for creating that hero. This helps during debugging, because you can skip to scenarios and the recall-or-create functionality means that any units which are normally met in a previous scenario are automatically created (otherwise some scenarios may be an instant loss). This can only be used for units that must survive the previous scenarios, as it would recreate units if they died in a previous scenario.&lt;br /&gt;
For example,&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/blob/1.14.7/data/campaigns/Heir_To_The_Throne/utils/httt_utils.cfg#L685 HttT's NEED_DELFADOR macro].&lt;br /&gt;
&lt;br /&gt;
=== [recall] ===&lt;br /&gt;
Recalls a unit taking into account any [[SingleUnitWML|filter_recall]] of the leader.   The unit is recalled free of charge, and is placed near its leader, e.g., if multiple leaders are present, near the first found which would be able to normally recall it.&lt;br /&gt;
&lt;br /&gt;
If neither a valid map location is provided nor a leader on the map would be able to recall it, the tag is ignored.&lt;br /&gt;
 &lt;br /&gt;
* [[StandardUnitFilter]]: the first matching unit will be recalled.  If no units match this tag is ignored. Do not use a [filter] tag. If a comma separated list is given, every unit currently considered for recall is checked against all the types (not each single one of the types against all units).&lt;br /&gt;
* '''x,y''': the unit is placed here instead of next to the leader.&lt;br /&gt;
* '''location_id''': {{DevFeature1.15|0}} the name of a special map location to recall to. Used instead of '''x,y'''.&lt;br /&gt;
* '''show''': yes/no, default yes: whether the unit is animated (faded in) or instantly displayed&lt;br /&gt;
* '''fire_event''': boolean yes|no (default no); whether any according prerecall or recall events shall be fired.&lt;br /&gt;
* '''check_passability''': (boolean yes|no, default yes): If yes, checks for terrain passability when placing the unit (a nearby passable hex is chosen).&lt;br /&gt;
* '''[secondary_unit]''': {{DevFeature1.13|?}} If present and show=yes, a matching unit will be chosen and their recruiting animation played.&lt;br /&gt;
&lt;br /&gt;
=== [teleport] ===&lt;br /&gt;
Teleports a unit on map. {{Short Note:Predefined Macro|TELEPORT_UNIT}}&lt;br /&gt;
* '''[filter]''': [[StandardUnitFilter]] the first unit matching this filter will be teleported.&lt;br /&gt;
* '''x,y''': the hex to teleport to. If that hex is occupied, the closest unoccupied hex will be used instead.&lt;br /&gt;
* '''location_id''': {{DevFeature1.15|0}} the name of a special map location to teleport to. Used instead of '''x,y'''.&lt;br /&gt;
* '''clear_shroud''': should shroud be cleared on arrival&lt;br /&gt;
* '''animate''': should a teleport animation be played (if the unit doesn't have a teleport animation, it will fade out/fade in)&lt;br /&gt;
* '''check_passability''': (boolean yes|no, default yes): normally, units will not be teleported into terrain that is impassable for them. Setting this attribute to &amp;quot;no&amp;quot; permits it.&lt;br /&gt;
&lt;br /&gt;
(Note: There is also a ability named teleport, see [[AbilitiesWML]].)&lt;br /&gt;
&lt;br /&gt;
=== [terrain_mask] ===&lt;br /&gt;
Changes the terrain on the map.  See [[TerrainMaskWML]].&lt;br /&gt;
&lt;br /&gt;
=== [terrain] ===&lt;br /&gt;
Changes the terrain on the map.&lt;br /&gt;
* '''terrain''': the character of the terrain to use.  See [[TerrainCodesWML]] to see what letter a type of terrain uses.&lt;br /&gt;
* [[StandardLocationFilter]]. This [[StandardLocationFilter]]'s terrain= key is used for the new terrain, filtering by terrain can be done with a nested [[StandardLocationFilter]]: [and]terrain=terrain_string_to_be_filtered_for.&lt;br /&gt;
* '''layer''': (overlay|base|both, default=both) only change the specified layer.&lt;br /&gt;
* '''replace_if_failed''': (default=no) When replacing just one layer failed, try to replace the whole terrain. If '''terrain''' is an overlay only terrain, use the default_base as base layer. If the terrain has no default base, do nothing.&lt;br /&gt;
* '''location_id''': This key sets a string as a way to mark the hex or hexes for later reference.  It is very similar to the leader starting position, and can also be set that way in the map editor.&lt;br /&gt;
&lt;br /&gt;
If you want to remove the overlays from a terrain and leave only the base, use:&lt;br /&gt;
 layer=overlay&lt;br /&gt;
 terrain=&amp;quot;^&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; When a hex changes from a village terrain to a non-village terrain, and a team owned that village it loses that village. When a hex changes from a non-village terrain to a village terrain and there is a unit on that hex it does not automatically capture the village. The reason for not capturing villages is that there are too many choices to make; should a unit lose its movement points, should capture events be fired. It is easier to do this as wanted by the author in WML.&lt;br /&gt;
&lt;br /&gt;
=== [gold] ===&lt;br /&gt;
Gives sides gold.&lt;br /&gt;
* '''amount''': the amount of gold to give.&lt;br /&gt;
* '''side''': (default=1) the number of the side to give the gold to. Can be a comma-separated list of sides. note: Default side=1 for empty side= is deprecated.&lt;br /&gt;
* [[StandardSideFilter]] tags and keys; default for empty side= is all sides, as usual in a SSF.&lt;br /&gt;
&lt;br /&gt;
=== [unstore_unit] ===&lt;br /&gt;
Creates a unit from a game variable, and activates it on the playing field or recall list.  This must be a specific variable describing a unit, and may not be an array (if it is, only the first unit will be unstored).&lt;br /&gt;
&lt;br /&gt;
This may be useful in different contexts:&lt;br /&gt;
* To update a unit on the map after having edited its WML. This usage is common, but discouraged - if possible, you should use [[#.5Bmodify_unit.5B|[modify_unit]]] or [[#.5Bobject.5B|[object]]] instead.&lt;br /&gt;
* To place a previously-defined unit into the scenario, if it was directly defined in a WML variable, using [unit] with the key '''to_variable'''. This usage is rather uncommon.&lt;br /&gt;
* To place a unit back into the game that was removed earlier, for example a hero that leaves the party for awhile and then comes back.&lt;br /&gt;
&lt;br /&gt;
The variable is not cleared. To unstore units from an array variable, iterate over the array. See [[VariablesWML]] and [[VariablesWML/How to use variables]] for more information about variable usage. See also [[InternalActionsWML#.5Bstore_unit.5D|[store_unit]]], [[ConditionalActionsWML|For]], [[ConditionalActionsWML#.5Bwhile.5D|[while]]] and [[InternalActionsWML#.5Bclear_variable.5D|[clear_variable]]].&lt;br /&gt;
&lt;br /&gt;
The tag takes the following keys:&lt;br /&gt;
* '''variable''': This is required to indicate the name of the variable to read the unit from.&lt;br /&gt;
* '''Placement keys''':&lt;br /&gt;
** '''x''' ,'''y''': By default, the unit will be placed at the location specified in the variable, but if these keys are present, the unit will be placed at that location instead. To place the unit on the recall list of its side, use '''x,y=recall,recall'''. (If you want to change the said, you need to first update ''$unit.side'' in the variable before unstoring.)&lt;br /&gt;
** '''location_id''': {{DevFeature1.15|0}} The name of a special map location to unstore to. Used instead of '''x,y'''.&lt;br /&gt;
** '''find_vacant''' (yes|no, default no): Whether the unit should be placed on the nearest vacant tile to its specified location. If this is set to 'no' (default), then any unit on the same tile as the unit being unstored will be destroyed.&lt;br /&gt;
** '''check_passability''' (yes|no, default yes): Only relevant if '''find_vacant=yes'''. In that case, this determines whether game will try to find a passable tile for the unit. If set to no, the unit may be placed on an impassable tile. Note that if both '''find_vacant''' and '''check_passability''' are set, then the unit's position may be shifted even if there is not a unit on the target space, if that space is not passable for the unit.&lt;br /&gt;
* '''Animation keys''' (these determine the visual effect of how the unit is placed or updated):&lt;br /&gt;
** '''text''': (translatable) A floating text to display above the unit, such as a damage amount.&lt;br /&gt;
** '''male_text''', '''female_text''': {{DevFeature1.13|2}} (translatable) gender-specific versions of the above&lt;br /&gt;
** '''red''', '''green''', '''blue''': (default=0,0,0) the color of the text. Values vary from 0-255. You may find it convenient to use the {COLOR_HARM} or {COLOR_HEAL} macro instead. (Use {COLOR_HARM} or {COLOR_HEAL} instead of the whole red,green,blue= line.)&lt;br /&gt;
** '''animate''': (boolean yes|no, default yes) Determines whether to play any animations associated with the unstore. Currently this only affects the advancement animation (&amp;quot;levelout&amp;quot; and &amp;quot;levelin&amp;quot;, defaulting to a fade to white and back) if the unit ends up advancing.&lt;br /&gt;
* '''Side-effect keys''' (these directly modify the behaviour of the action):&lt;br /&gt;
** '''advance''': (default=yes) if yes the unit is advanced if it has enough XP. When modifying XP, make sure to do it from inside a [[EventWML#Multiplayer_safety|synchronized event]] or it may lead to OOS errors, especially when several advancement paths exist. Note that advance and post advance events are called, so infinite loops can happen.&lt;br /&gt;
** '''fire_event''' (yes|no, default no): Whether any advance/post advance events shall be fired if an advancement takes place. This also affects whether the unit placed event is fired.&lt;br /&gt;
&lt;br /&gt;
Units can be unstored with negative (or zero) hit points. This can be useful if modifying a unit in its last_breath event (as the unit's death is already the next step), but tends to look wrong in other cases. In particular, it is possible to have units with negative hit points in play. Such units are aberrations, subject to unusual behavior as the game compensates for them. (For example, such units are currently automatically hit&amp;amp;mdash;and killed&amp;amp;mdash;in combat.) The details of the unusual behavior are subject to change between stable releases without warning.&lt;br /&gt;
&lt;br /&gt;
=== [allow_recruit] ===&lt;br /&gt;
Allows a side to recruit units it couldn't previously recruit. Any leader on this side will now be able to recruit the new units.&lt;br /&gt;
* '''type''': the types of units that the side can now recruit.&lt;br /&gt;
* '''side''': (default=1) the number of the side that is being allowed to recruit the units. This can be a comma-separated list note: Default side=1 for empty side= is deprecated.&lt;br /&gt;
* [[StandardSideFilter]] tags and keys; default for empty side= is all sides, as usual in a SSF.&lt;br /&gt;
&lt;br /&gt;
=== [allow_extra_recruit] ===&lt;br /&gt;
Allows a leader to recruit units it couldn't previously recruit.&lt;br /&gt;
These types are in addition to the types the leader can recruit because of '''[side]recruit=''' and '''[allow_recruit]'''.&lt;br /&gt;
* '''extra_recruit''': the types of units that the leader can now recruit.&lt;br /&gt;
* '''[[StandardUnitFilter]]''': All units matching this filter are modified. Does not match on recall list units.&lt;br /&gt;
&lt;br /&gt;
=== [disallow_recruit] ===&lt;br /&gt;
Prevents a side from recruiting units it could previously recruit. No leader on this side will be able to recruit the specified units anymore, unless that leader has the same unit in their personal '''extra_recruit''' list.&lt;br /&gt;
* '''type''': the types of units that the side can no longer recruit. {{DevFeature1.13|0}} If omitted, all recruits for matching sides will be disallowed.&lt;br /&gt;
* '''side''': (default=1) the number of the side that may no longer recruit the units. This can be a comma-separated list note: Default side=1 for empty side= is deprecated.&lt;br /&gt;
* [[StandardSideFilter]] tags and keys; default for empty side= is all sides, as usual in a SSF.&lt;br /&gt;
&lt;br /&gt;
=== [disallow_extra_recruit] ===&lt;br /&gt;
Prevents a leader from recruiting units it could previously recruit. This won't prevent the leader from recruiting that unit if the unit is in the '''[side]recruit=''' list – you must use '''[disallow_recruit]''' in that case.&lt;br /&gt;
* '''extra_recruit''': the types of units that the leader can no longer recruit.&lt;br /&gt;
* '''[[StandardUnitFilter]]''': All units matching this filter are modified. Does not match on recall list units.&lt;br /&gt;
&lt;br /&gt;
=== [set_recruit] ===&lt;br /&gt;
Sets the units a side can recruit. Any leader on this side will now be able to recruit these units.&lt;br /&gt;
* '''recruit''': the types of units that the side can now recruit.&lt;br /&gt;
* '''side''': The number of the side that is having its recruitment set. This can be a comma-separated list.&lt;br /&gt;
* [[StandardSideFilter]] tags and keys; default for empty side= is all sides, as usual in a SSF.&lt;br /&gt;
&lt;br /&gt;
=== [set_extra_recruit] === &lt;br /&gt;
Sets the units a leader can recruit.&lt;br /&gt;
These types are in addition to the types the leader can recruit because of '''[side]recruit=''' and '''[set_recruit]'''.&lt;br /&gt;
* '''extra_recruit''': the types of units that the leader can now recruit.&lt;br /&gt;
* '''[[StandardUnitFilter]]''': All units matching this filter are modified. Does not match on recall list units.&lt;br /&gt;
&lt;br /&gt;
=== [modify_side] ===&lt;br /&gt;
Modifies some details of a given side in the middle of a scenario.  '''The following listed properties are the only properties that [modify_side] can affect!'''&lt;br /&gt;
* '''side''': (default=1) the number of the side that is to be changed. note: Default side=1 for empty side= is deprecated.&lt;br /&gt;
* '''[filter_side]''' with a [[StandardSideFilter]] as argument&lt;br /&gt;
* '''income''': the income given at the begining of each turn.&lt;br /&gt;
* '''recruit''': a list of unit types, replacing the side's current recruitment list.&lt;br /&gt;
* '''team_name''': the team in which the side plays the scenario.&lt;br /&gt;
* '''user_team_name''': a translatable string representing the team's description. This has no effect on alliances. Defaults to ''team_name''.&lt;br /&gt;
* '''side_name''': {{DevFeature1.13|?}} a translatable string representing the side leader's description.&lt;br /&gt;
* '''gold''': the amount of gold the side owns.&lt;br /&gt;
* '''village_gold''': the income setting per village for the side.&lt;br /&gt;
* '''controller''': the identifier string of the side's controller. Uses the same syntax of the ''controller'' key in the [[SideWML|[side]]] tag. warning: in multiplayer, changing the controller of a side might result in OOS during some events like, for example 'side_turn_end'; see [https://github.com/wesnoth/wesnoth/issues/2563 issue #2563].&lt;br /&gt;
* '''fog''': a boolean string (yes/no) describing the status of Fog for the side.&lt;br /&gt;
* '''shroud''': a boolean string describing the status of Shroud for the side.&lt;br /&gt;
* '''hidden''': a boolean string specifying whether side is shown in status table.&lt;br /&gt;
* '''color''': a team color range specification, name (e.g. &amp;quot;red&amp;quot;, &amp;quot;blue&amp;quot;), or number (e.g. &amp;quot;1&amp;quot;, &amp;quot;2&amp;quot;) for this side. The default color range names, numbers, and definitions can be found in data/core/team_colors.cfg.&lt;br /&gt;
* '''[ai]''': sets/changes AI parameters for the side. Only parameters that are specified in the tag are changed, this does not reset others to their default values. Uses the same syntax as described in [[AiWML]].  Note that [modify_side][ai] works for all simple AI parameters and some, but not all, of the composite ones. If in doubt, use [[AiWML#Adding_and_Deleting_Aspects_with_the_.5Bmodify_ai.5D_Tag|[modify_ai]]]] instead, which always works. {{DevFeature1.13|?}} If this contains an '''ai_algorithm''', the AI parameters will be reset to those of the indicated AI before adding any additional parameters included in the tag. In other words, this allows replacing the AI config rather than appending to it.&lt;br /&gt;
* '''switch_ai''': replaces a side ai with a new AI from specified file(ignoring those AI parameters above). Path to file follows the usual WML convention.&lt;br /&gt;
* '''reset_maps''': If set to &amp;quot;yes&amp;quot;, then the shroud is spread to all hexes, covering the parts of the map that had already been explored by the side, including hexes currently seen. (Seen hexes will be cleared at the end of most events; they can also be manually cleared with {{tag|InterfaceActionsWML|redraw}}.) This is only effective if shroud is on, but this is evaluated after shroud= (and before shroud_data=).&lt;br /&gt;
* '''reset_view''': If set to &amp;quot;yes&amp;quot;, then the fog of war is spread to all hexes, covering the parts of the map that had already been seen this turn by the side, including hexes currently seen, excluding hexes affected by multi-turn {{tag|DirectActionsWML|lift_fog}}. (Seen hexes will be cleared at the end of most events; they can also be manually cleared with {{tag|InterfaceActionsWML|redraw}}.) This is only effective if fog is on, but this is evaluated after fog=.&lt;br /&gt;
* '''share_maps''': change the share_maps side attribute. Be sure to use shroud=yes for that side and have it as an ally&lt;br /&gt;
* '''share_view''': change the share_view side attribute. Be sure to use fog=yes for that side and have it as an ally&lt;br /&gt;
* '''share_vision''': change both the above at the same time&lt;br /&gt;
* '''shroud_data''': changes to the side's shroud, using the same format as when defining the [side].&lt;br /&gt;
* '''suppress_end_turn_confirmation''': Boolean value controlling whether or not a player is asked for confirmation when skipping a turn.&lt;br /&gt;
* '''scroll_to_leader''': Boolean value controlling whether or not the game view scrolls to the side leader at the start of their turn when present.&lt;br /&gt;
* '''flag''': Flag animation for villages owned by this side (see [[SideWML|[side]]]).&lt;br /&gt;
* '''flag_icon''': Flag icon used for this side in the status bar (see [[SideWML|[side]]]).&lt;br /&gt;
* '''village_support''': The number of unit levels this side is able to support (does not pay upkeep on) per village it controls.&lt;br /&gt;
* '''defeat_condition''' {{DevFeature1.13|0}}: When the side is considered defeated (see [[SideWML|[side]]]).&lt;br /&gt;
* '''[set_variable]''', '''[clear_variable]''' {{DevFeature1.15|3}} Sets or clears a variable within the side; uses the same syntax as [[InternalActionsWML#.5Bset_variable.5D|[set_variable]]] or [[InternalActionsWML#.5Bclear_variable.5D|[clear_variable]]] in ActionWML.&lt;br /&gt;
* '''[variables]''' {{DevFeature1.15|3}} The contents of this tag is merged into the side's variables.&lt;br /&gt;
&lt;br /&gt;
=== [modify_turns] ===&lt;br /&gt;
Modifies the turn limit in the middle of a scenario.&lt;br /&gt;
* '''value''': the new turn limit.&lt;br /&gt;
* '''add''': if used instead of ''value'', specifies the number of turns to add to the current limit (can be negative).&lt;br /&gt;
* '''current''': changes the current turn number after applying turn limit modifications, if any. It is not possible to change the turn number to exceed the turn limit (1 &amp;lt;= current turns &amp;lt;= max turns).&lt;br /&gt;
&lt;br /&gt;
=== [allow_end_turn] ===&lt;br /&gt;
Allows human players to end their turn through the user interface if they were previously affected by the '''[disallow_end_turn]''' action. This action doesn't take any arguments.&lt;br /&gt;
&lt;br /&gt;
=== [disallow_end_turn] ===&lt;br /&gt;
Disallows human players to end their turn through the user interface. This action doesn't require arguments.&lt;br /&gt;
* '''reason''' (translatable): {{DevFeature1.15|0}} Allows to optionally specify a reason.&lt;br /&gt;
&lt;br /&gt;
=== [capture_village] ===&lt;br /&gt;
Changes the ownership of a village.&lt;br /&gt;
* [[StandardLocationFilter]]: all village locations matching the filter are affected.&lt;br /&gt;
* '''side''': the side that takes control of the village. This side needs to have a leader (canrecruit=yes). If the side key is not given, the village will become neutral (unless [filter_side] is present, in which case that side fiter decides, see below).&lt;br /&gt;
* '''[filter_side]''' with [[StandardSideFilter]] tags and keys as arguments; if both this tag and inline side= are present it's an error. Otherwise, the first matching side gets ownership (or the village becomes neutral if none match).&lt;br /&gt;
* '''fire_event''' (boolean yes|no, default: no): Whether any capture events shall be fired.&lt;br /&gt;
&lt;br /&gt;
=== [kill] ===&lt;br /&gt;
Removes all units (including units in a recall list) that match the filter from the game.&lt;br /&gt;
* [[StandardUnitFilter]]: Selection criterion; do not use a [filter] tag.&lt;br /&gt;
* '''animate''' (default 'no'): if 'yes', displays the unit dying (fading away). {{DevFeature1.13|8}} If '''[secondary_unit]''' is given, also plays the victory animation of that unit.&lt;br /&gt;
* '''fire_event''' (default 'no'): if 'yes', triggers any appropriate 'die' events (See [[EventWML]]). Note that events are only fired for killed units that have been on the map (as opposed to recall list).&lt;br /&gt;
* '''[secondary_unit]''' with a [[StandardUnitFilter]] as argument. Do not use a [filter] tag. Has an effect only if fire_event=yes ({{DevFeature1.13|8}} or if it has a victory animation and animate=yes). The first on-map unit matching the filter becomes second_unit in any fired die and last breath events. If an on-map unit matches and if there are several units killed with a single [kill] tag, second_unit is this same unit for all of them. If no on-map unit matches or [secondary_unit] isn't present, the variable second_unit in each of the die and last breath events is always the same as the variable unit (the dying unit).&lt;br /&gt;
* '''[primary_attack]''' {{DevFeature1.13|8}} The attacker's weapon to use for matching the animation. Useful for example on the wose, whose death animation depends on the damage type it was killed by. If a secondary unit is specified, this is taken as a [[StandardWeaponFilter]] and used to find a matching weapon on the unit. However, if there is no secondary unit specified, it is instead treated as an [[UnitTypeWML#Attacks|weapon definition]], and the animation will be run as if an imaginary unit possessing that weapon was the attacker.&lt;br /&gt;
* '''[secondary_attack]''' {{DevFeature1.13|8}} Similar to the above, but for the defender's weapon. This is taken as a [[StandardWeaponFilter]] and used to find a matching weapon on the dying unit.&lt;br /&gt;
&lt;br /&gt;
=== [move_unit] ===&lt;br /&gt;
Moves a unit along a path on the map. The path can be specified exactly, or as a series of waypoints that the unit will pass through.&lt;br /&gt;
* [[StandardUnitFilter]] as argument; do not use a [filter] tag. All units matching the filter are moved. If the target location is occupied, the nearest free location is chosen.&lt;br /&gt;
* '''to_x''' (unsigned integer): The units are moved to this x coordinate. Can be a comma-separated list, in which case the unit follows this given path during the move.&lt;br /&gt;
* '''to_y''' (unsigned integer): The units are moved to this y coordinate. Can be a comma-separated list.&lt;br /&gt;
* '''dir''' (string): {{DevFeature1.15|0}} Performs a relative movement instead of an absolute movement. For example, dir=n,n,nw will move two spaces north and then one space to the northwest. This is used instead of '''to_x''' and '''to_y'''.&lt;br /&gt;
* '''to_location''': {{DevFeature1.15|0}} Moves matching units to locations placed in the map editor with the &amp;quot;New Location&amp;quot; button. Can be a comma-separated list. This is used instead of '''to_x''' and '''to_y'''.&lt;br /&gt;
* '''check_passability''' (boolean yes|no, default yes): Whether the terrain the unit is moved to should be checked for suiting the unit. (If it does not, a nearby suitable hex is chosen.)&lt;br /&gt;
* '''force_scroll''': Whether to scroll the map or not even when [[InterfaceActionsWML#.5Block_view.5D|[lock_view]]] is in effect or ''Follow Unit Actions'' is disabled in ''Advanced Preferences''. Defaults to using [[InterfaceActionsWML#.5Bmove_unit_fake.5D|[move_unit_fake]]]'s default value.&lt;br /&gt;
* '''clear_shroud''': {{DevFeature1.15|0}} (boolean yes|no, default no) Whether to remove shroud and fog after the unit was moved, but before events are fired. It will not clear all alongside the path, only around the target destination.&lt;br /&gt;
* '''fire_event''' (boolean yes|no, default no): Whether any according moveto events shall be fired. The target location ($x1, $y1 in the event) may not be the same location that the unit was tried to be moved to, if the original target location is occupied or impassable.&lt;br /&gt;
&lt;br /&gt;
=== [modify_ai] ===&lt;br /&gt;
Changes AI objects (aspects, goals, candidate actions or stages) for a specified side. See [[Modifying_AI_Components#The_.5Bmodify_ai.5D_Tag|Modifying AI Components]] for full description.&lt;br /&gt;
&lt;br /&gt;
* '''action''' (string): Takes values 'add', 'change', 'delete' or 'try_delete' to do just that for the AI object.&lt;br /&gt;
* '''path''' (string): Describes which AI object is to be modified.  &lt;br /&gt;
* '''[facet]''', '''[goal]''', '''[candidate_action]''' or '''[stage]''': Details about the AI object to be modified.&lt;br /&gt;
* [[StandardSideFilter]] tags and keys; default for empty side= is all sides, as usual in a SSF.&lt;br /&gt;
&lt;br /&gt;
=== [modify_unit] ===&lt;br /&gt;
works similar to the MODIFY_UNIT macro.&lt;br /&gt;
* '''[filter]''' with a [[StandardUnitFilter]] as argument. All units matching this filter are modified. Matches on recall list units too.&lt;br /&gt;
* '''[object]''', '''[trait]''', {{DevFeature1.13|5}} '''[advancement]''' - The given modifications will be immediately applied to all units matching the filter. ([object] is described further [[#.5Bobject.5D|below]])&lt;br /&gt;
** '''delayed_variable_substitution''' {{DevFeature1.13|5}} (boolean yes|no, default no): If set to &amp;quot;yes&amp;quot;, the wml block contained in this [object], [trait], or [advancement] is not variable-substituted at execution time of the event containing this [modify_unit]. You need this for any effect that uses variable substitution or when using [effect][filter] with a $this_unit. {{DevFeature1.13|9}} This is no longer needed when adding ABILITY_TELEPORT, ABILITY_LEADERSHIP or SPECIAL_BACKSTAB.&lt;br /&gt;
** Do not use a '''[modifications]''' tag, as this may skip some of the special-case handling for newly added objects, traits and advancements, and will potentially overwrite existing modifications.&lt;br /&gt;
* '''[effect]''' {{DevFeature1.13|6}} Applies the effect directly to the unit. See [[EffectWML]].&lt;br /&gt;
* '''[set_variable]''', '''[clear_variable]''' {{DevFeature1.15|3}} Sets or clears a variable within the unit (saved inside the unit's [variables] tag); uses the same syntax as [[InternalActionsWML#.5Bset_variable.5D|[set_variable]]] or [[InternalActionsWML#.5Bclear_variable.5D|[clear_variable]]] in ActionWML.&lt;br /&gt;
* Accepts generally the syntax inside of wml unit variables created by [store_unit] which can be viewed in a savefile or by using the [[CommandMode|inspect command]]. Cannot remove things or add/alter unit animations. Subtags with the same name must be written in the correct order to match them with the tag they are supposed to modify. Note that keys will be processed in arbitrary order, which may cause problems if you use formulas that depend on other formulas. To work around this you may need to use the tag twice with the same filter.&lt;br /&gt;
example usage (see also the test scenario):&lt;br /&gt;
&amp;lt;syntaxhighlight lang='wml'&amp;gt;&lt;br /&gt;
[modify_unit]&lt;br /&gt;
  [filter]&lt;br /&gt;
    x,y=38,6&lt;br /&gt;
  [/filter]&lt;br /&gt;
  hitpoints=10&lt;br /&gt;
  {TRAIT_HEALTHY}&lt;br /&gt;
[/modify_unit]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The unit which is currently modified is accessible via $this_unit, e.g. hitpoints = &amp;quot;$($this_unit.hitpoints / 2)&amp;quot; to set the hitpoints of all units to half of their current value. This this_unit variable is independent from the this_unit variable available in the SUF used to determine which units to modify (first all matching units are gathered, and then all those are modified).&lt;br /&gt;
&lt;br /&gt;
Modifying a unit ''may'' trigger an advancement event if the experience is set higher than the max_experience. However, this behaviour should not be relied upon to happen under all circumstances; if it's desired, the event should be triggered separately, for example with '''[transform_unit]'''.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Some some properties of the units are reset sometimes (for example when the unit advances or when [remove_object] is called), so it's usually better to change them with [object] ([object] inside [modify_unit]) than to change those properties directly via [modify_unit]. The following properties are _not_ reset in [remove_object] and are thus safe to use directly in [modify_unit]:&lt;br /&gt;
* '''side'''&lt;br /&gt;
* '''gender'''&lt;br /&gt;
* '''name'''&lt;br /&gt;
* '''canrecruit'''&lt;br /&gt;
* '''unrenamable'''&lt;br /&gt;
* '''extra_recruit'''&lt;br /&gt;
* '''[variables]'''&lt;br /&gt;
* '''facing'''&lt;br /&gt;
* '''x, y'''&lt;br /&gt;
* '''goto_x, goto_y'''&lt;br /&gt;
* '''hitpoints'''&lt;br /&gt;
* '''experience'''&lt;br /&gt;
* '''moves'''&lt;br /&gt;
* '''[status]'''&lt;br /&gt;
* '''attacks_left'''&lt;br /&gt;
* '''role'''&lt;br /&gt;
&lt;br /&gt;
=== [transform_unit] ===&lt;br /&gt;
Transforms every unit on the map matching the filter to the given unit type. Keeps intact hit points, experience and status. If the unit is transformed to a non-living type (undead or mechanical), it will be also unpoisoned. Hit points will be changed if necessary to respect the transformed unit's maximum hit points. Regardless of anything else, the unit will be rebuilt. Thus, transforming a unit to its current type is a way to force a rebuild, for example after manually removing a modification.&lt;br /&gt;
* [[StandardUnitFilter]]: do not use a [filter] tag.&lt;br /&gt;
* '''transform_to''': the unit type in which all the units matching the filter will be transformed. If missing, the units will follow their normal advancement.&lt;br /&gt;
&lt;br /&gt;
=== [petrify] ===&lt;br /&gt;
&lt;br /&gt;
* [[StandardUnitFilter]] as an argument. Do not use a [filter] tag. All units matching this filter are petrified. Recall list units are included.&lt;br /&gt;
&lt;br /&gt;
=== [unpetrify] ===&lt;br /&gt;
* [[StandardUnitFilter]] as an argument. Do not use a [filter] tag. All units matching this filter are unpetrified. Recall list units are included.&lt;br /&gt;
&lt;br /&gt;
=== [object] ===&lt;br /&gt;
Gives some unit an object which modifies their stats in some way. This tag can also be used in places that don't support ActionWML, such as [[#.5Bmodify_unit.5D|[modify_unit]]] or [[SingleUnitWML|[unit][modifications]]]. The following is supported in all these places:&lt;br /&gt;
* '''[effect]''': one or more effect elements may be listed.  See [[EffectWML]] for a description of [effect].&lt;br /&gt;
* '''duration''':&lt;br /&gt;
**if 'scenario', effects only last until the end of the scenario.&lt;br /&gt;
**if 'forever' or not set, effects never wear off.&lt;br /&gt;
** if 'turn', effects only last until the start of the unit's next turn (when the unit refreshes movement and attacks). (Like other start-of-turn behavior, objects with a duration of &amp;quot;turn&amp;quot; won't expire before turn 2.)&lt;br /&gt;
** {{DevFeature1.13|1}} if 'turn end', effects only last until the end of the unit's next turn (exactly like the slowed status).&lt;br /&gt;
* Other keys, such as '''id''', may be used to remove the object later, but are not used by the engine. An '''[object]''' tag can contain any arbitrary data that may be helpful to identify the object to remove later using a [[FilterWML#Filtering_on_WML_data|WML filter]].&lt;br /&gt;
&lt;br /&gt;
The following is supported only when using '''[object]''' as ActionWML:&lt;br /&gt;
* '''id''': (Optional) By default, an object with a defined ID can only be picked up once per scenario, even if it is removed later or first_time_only=no is set for the event. You can remove this restriction by setting take_only_once=no. For filtering objects, it might be simpler to use a custom key such as item_id. The id string can contain only letters, numbers and underscores. The ID is also commonly used to manually remove the object later, for example with [[#.5Bremove_object.5D|[remove_object]]].&lt;br /&gt;
* '''take_only_once''': (default yes) {{DevFeature1.13|6}} If set to &amp;quot;no&amp;quot;, the object's ID does not prevent it from being taken more than once.&lt;br /&gt;
* '''delayed_variable_substitution''' (boolean yes|no, default no): If set to &amp;quot;yes&amp;quot;, the wml block contained in this [object] is not variable-substituted at execution time of the event where this [object] is within.  You need this for any effect that uses variable substitution or when using [effect][filter] with a $this_unit. {{DevFeature1.13|9}} This is no longer needed when adding ABILITY_TELEPORT, ABILITY_LEADERSHIP or SPECIAL_BACKSTAB.&lt;br /&gt;
* '''[filter]''' with a [[StandardUnitFilter]] as argument. The first unit found that matches the filter will be given the object. Only on-map units are considered. If no unit matches or no [filter] is supplied, it tries to apply the object to the unit at the $x1,$y1 location of the event where this [object] is in. The case of no unit being at that spot is handled in the same way as no unit matching a given filter ([else] commands executed, cannot_use_message displayed). Note that units on the recall list will not be checked. To add an [object] to a unit on the recall list you have to use '''[modify_unit][object]'''.&lt;br /&gt;
* '''[then]''': a subtag that lets you execute actions if the filter conditions are met.  The most common action that should be inside here is a '''[remove_item]''' tag, but you could probably put any tags that otherwise work in a [then] tag.&lt;br /&gt;
* '''[else]''': a subtag that lets you execute actions if the filter conditions are *not* met.&lt;br /&gt;
* '''silent''': whether or not messages should be suppressed. Default is &amp;quot;no&amp;quot;. {{DevFeature1.13|2}} If no description is provided, this defaults to yes, but can still be overridden.&lt;br /&gt;
* '''image''': the displayed image of the object.&lt;br /&gt;
* '''name''': (translatable) displayed as a caption of the image.&lt;br /&gt;
* '''description''': (translatable) displayed as a message of the image.&lt;br /&gt;
* '''cannot_use_message''': (translatable) displayed instead of '''description''' if no unit passes the filter test.&lt;br /&gt;
&lt;br /&gt;
=== [remove_object] ===&lt;br /&gt;
{{DevFeature1.13|6}}&lt;br /&gt;
&lt;br /&gt;
Removes an object from matching units.&lt;br /&gt;
&lt;br /&gt;
* [[StandardUnitFilter]]: All units on the map (but not the recall list) matching the filter have matching objects removed. Use no [filter] tag.&lt;br /&gt;
* '''object_id''': The id of the object to be removed.&lt;br /&gt;
&lt;br /&gt;
Note that some unit properties are not restored ideally, e.g. current unit's health reversion might not work as expected (max_hitpoints will though). {{DevFeature1.15|0}} This was fixed.&lt;br /&gt;
&lt;br /&gt;
Note that [remove_object] works the following way: &lt;br /&gt;
&lt;br /&gt;
# Remove the object from the unit&lt;br /&gt;
# Rebuild the unit to make the changes effective.&lt;br /&gt;
&lt;br /&gt;
Step 2 implies that changes done for example via [modify_unit] (or via the [store_unit] + [set_variable] + [unstore_unit] technique) will be reset if those changes change a property that is a property of the unit type. See the note under [[#.5Bmodify_unit.5D|[modify_unit]]] to get a list of properties that can safely be changed via [modify_unit].&lt;br /&gt;
&lt;br /&gt;
=== [remove_trait] ===&lt;br /&gt;
{{DevFeature1.15|2}}&lt;br /&gt;
&lt;br /&gt;
* [[StandardUnitFilter]]: All units on the map (but not the recall list) matching the filter have matching traits removed. Use no [filter] tag.&lt;br /&gt;
* '''trait_id''': The id of the trait to be removed. See [[UnitsWML#.5Btrait.5D|[trait]]].&lt;br /&gt;
&lt;br /&gt;
=== [remove_shroud] ===&lt;br /&gt;
Removes some shroud from the map for a certain side (only relevant for sides that have shroud=yes).&lt;br /&gt;
* '''side''': (default=1) the side for which to remove shroud. This can be a comma-separated list of sides. note: Default side=1 for empty side= is deprecated.&lt;br /&gt;
* '''[filter_side]''' with a [[StandardSideFilter]] as argument&lt;br /&gt;
* [[StandardLocationFilter]]: the range of tiles for which shroud should be removed&lt;br /&gt;
&lt;br /&gt;
=== [place_shroud] ===&lt;br /&gt;
Places some shroud on the map for a certain side (only relevant for sides that have shroud=yes).&lt;br /&gt;
* '''side''': (default=1) the side for which to place shroud. This can be a comma-separated list. note: Default side=1 for empty side= is deprecated.&lt;br /&gt;
* '''[filter_side]''' with a [[StandardSideFilter]] as argument&lt;br /&gt;
* [[StandardLocationFilter]]: the range of tiles on which shroud should be placed&lt;br /&gt;
&lt;br /&gt;
=== [lift_fog] ===&lt;br /&gt;
Lifts the fog of war from parts of the map for a certain side (only relevant for sides that have fog=yes), allowing a player to witness what occurs there even if that player has no units within vision range.&lt;br /&gt;
* '''[filter_side]''' with a [[StandardSideFilter]] indicating which sides should be affected.&lt;br /&gt;
* [[StandardLocationFilter]]: the tiles from which fog should be lifted.&lt;br /&gt;
* '''multiturn''': ''yes/no, default:no''. The default (not multiturn) causes fog to be removed in the same way that normal vision works; the cleared tiles will remain cleared until fog is recalculated (which normally happens when a side ends its turn). When multiturn is set to &amp;quot;yes&amp;quot;, the cleared tiles remain clear until {{tag||reset_fog}} cancels the clearing. This allows tiles to remain clear for multiple turns, or to be refogged before the end of the current turn (without also refogging all tiles). Multiturn lifted fog is not shared with allies (even when share_vision=all).&lt;br /&gt;
&lt;br /&gt;
=== [reset_fog] ===&lt;br /&gt;
The primary use of this tag is to remove multiturn lifted fog (created by {{tag||lift_fog}}), which causes the fog to reset to what it would have been had WML not interfered. (That is, hexes that a side's units could not see at any point this turn will be re-fogged, while seen hexes remain defogged.)&lt;br /&gt;
* '''[filter_side]''' with a [[StandardSideFilter]] indicating which sides should be affected.&lt;br /&gt;
* [[StandardLocationFilter]]: the fog reset will be restricted to these tiles.&lt;br /&gt;
* '''reset_view''': ''yes/no, default: no'' If set to &amp;quot;yes&amp;quot;, then in addition to removing multiturn fog, the side's current view is canceled (independent of the SLF). This means that all hexes will become fogged for the side unless multiturn fog exists outside the tiles selected by the SLF. Normally, one would want the currently seen hexes to become clear of fog; this is done automatically at the end of many events, and it can be done manually with {{tag|InterfaceActionsWML|redraw}}.&lt;br /&gt;
Omitting both the SSF and the SLF would cancel all earlier uses of [lift_fog].&lt;br /&gt;
Additionally setting reset_view=&amp;quot;yes&amp;quot; would cause the side's entire map to be fogged (unless an ally keeps hexes clear by sharing its view).&lt;br /&gt;
&lt;br /&gt;
=== [allow_undo] ===&lt;br /&gt;
Normally when an event with a handler fires, the player's undo stack is cleared, preventing all actions performed so far from being undone. Including this tag in the event handler prevents the stack from being cleared for this reason, allowing the player to undo actions. (However, the stack might still be cleared for other reasons, such as fog being cleared or combat occurring.) In the common cases, this means '''[allow_undo]''' allows the current action to be undone even though an event was handled. There is a less common case, though &amp;amp;mdash; specifically when handling a menu item, where there is no current action &amp;amp;mdash; and in this case, '''[allow_undo]''' means merely that earlier actions can still be undone.&lt;br /&gt;
* Using this tag in a menu item has an additional side effect in 1.11. Starting with version 1.11.1, executing a WML menu item normally counts as doing something as far as the &amp;quot;you have not started your turn yet&amp;quot; dialog is concerned. However, a menu item whose handler includes '''[allow_undo]''' will not count.&lt;br /&gt;
&lt;br /&gt;
The types of actions that can be undone are movement, recalling, and dismissing a unit from the recall list. If an action is undone, only the position (or existence) of the involved unit will be restored; any altered variables or changes to the game will remain changed after the action is undone.  It is up to the scenario designer to avoid abusing this command.&lt;br /&gt;
* Technically, if '''[allow_undo]''' is inside an '''[event]''' with ''first_time_only=yes'' (the default setting), and the user undoes the event, then the state of the game has changed in this way: the event will not fire a second time, even though the user undid the action the first time.&lt;br /&gt;
* Although recalling can be undone, recruitment can not be undone; this seems to apply even when the recruit's traits are not randomly-generated (tested on 1.12.6 and 1.14.4+dev).&lt;br /&gt;
&lt;br /&gt;
If an '''[event]''' uses both '''[allow_undo]''' and [[InternalActionsWML#.5Bfire_event.5D|'''[fire_event]''']] then the '''[allow_undo]''' must be after the '''[fire_event]'''.&lt;br /&gt;
&lt;br /&gt;
Due to a bug in 1.12 ([http://web.archive.org/web/20170330000414/http://gna.org/bugs/?23323 https://gna.org/bugs/?23323]) '''[allow_undo]''' should not be used in events that use one of the following things because it might cause OOS: &lt;br /&gt;
* [message] with [option]s&lt;br /&gt;
* [get_global_variable]&lt;br /&gt;
* wesnoth.synchronize_choice&lt;br /&gt;
&lt;br /&gt;
While in 1.13 using '''[allow_undo]''' together with those things won't give you a guaranteed OOS, there are some non-obvious situations where it will, for example assume the following event:&lt;br /&gt;
&lt;br /&gt;
   [event]&lt;br /&gt;
     name=&amp;quot;moveto&amp;quot;&lt;br /&gt;
     [message]&lt;br /&gt;
       message = &amp;quot;message&amp;quot;&lt;br /&gt;
       [option]&lt;br /&gt;
         label = &amp;quot;option 1&amp;quot;&lt;br /&gt;
         [command]&lt;br /&gt;
         [/command]&lt;br /&gt;
       [/option]&lt;br /&gt;
       [option]&lt;br /&gt;
         label = &amp;quot;option 2&amp;quot;&lt;br /&gt;
         [command]&lt;br /&gt;
         [/command]&lt;br /&gt;
       [/option]&lt;br /&gt;
     [/message]&lt;br /&gt;
     [allow_undo]&lt;br /&gt;
     [/allow_undo]&lt;br /&gt;
   [/event]&lt;br /&gt;
&lt;br /&gt;
It will cause OOS when the message is undone: since the event is already executed (erased) on one client only , the clients will disagree about how many choices happen during the next moveto action.&lt;br /&gt;
&lt;br /&gt;
=== [on_undo] ===&lt;br /&gt;
{{DevFeature1.13|2}}&lt;br /&gt;
Contains commands to execute when the player undoes the action which triggered the parent event.&lt;br /&gt;
*'''delayed_variable_substitution''' {{DevFeature1.13|5}}: ''yes/no, default no (always no before 1.13.5)'' As in [[EventWML]], specifies whether to perform variable substitution when the parent event is run, or when the contents are run. If delayed substitution is used, [[VariablesWML#Automatically_Stored_Variables|automatically stored variables]] from the parent event context are available, but may occasionally have unexpected values. (In particular, $unit.x and $unit.y may not have the expected value when undoing a move event, though $x1 and $y1 should be correct.)&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
It is not clear where whether the actionwml in [on_undo] in executed before or after the action is undone. Also, specially for enter/leave_hex events the units position when executing the [on_undo] code is usually different than when executing the original event. The recommended way to work around these issues is to refer to the unit by id instead of position and store all other needed information variables as 'upvalues'. You can also move the actual undo code to an external event. For example&lt;br /&gt;
 [event]&lt;br /&gt;
   name=&amp;quot;undo_blah&amp;quot;&lt;br /&gt;
   first_time_only=no&lt;br /&gt;
   [store_unit]&lt;br /&gt;
     id=&amp;quot;$moved_unit_id&amp;quot;&lt;br /&gt;
   [/store_unit]&lt;br /&gt;
   ... do undo stuff stuff&lt;br /&gt;
 [/event]&lt;br /&gt;
 &lt;br /&gt;
 ...&lt;br /&gt;
 ... in some other event&lt;br /&gt;
   [on_undo]&lt;br /&gt;
     # store ''upvalues&lt;br /&gt;
     {VARIABLE moved_unit_id $unit.id}&lt;br /&gt;
     # call actual undo handler&lt;br /&gt;
     [fire_event]&lt;br /&gt;
       name = &amp;quot;undo_blah&amp;quot;&lt;br /&gt;
     [/fire_event]&lt;br /&gt;
   [on_undo]&lt;br /&gt;
&lt;br /&gt;
=== [on_redo] ===&lt;br /&gt;
{{DevFeature1.13|2}}&lt;br /&gt;
Same as [on_undo], except executes the commands on redo. Note that the parent event is not triggered again on a redo.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|8}} [on_redo] is deprecated and has no effect anymore.&lt;br /&gt;
&lt;br /&gt;
Note that [on_redo] is not guaranteed to be called when redoing an action, the engine might also decide to just fire the original events again.&lt;br /&gt;
&lt;br /&gt;
=== [cancel_action] ===&lt;br /&gt;
Although Wesnoth 1.12 does not have this tag, it is the default behavior of '''enter_hex'''/'''exit_hex''' [event] in that version.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|9}} In this version, [cancel_action] is recognised, but has no effect (a bug).&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|11}}&lt;br /&gt;
In an '''enter_hex'''/'''exit_hex''' [event], interrupt the movement, leaving the unit where it is. This is intended to be used with an event that gives the player new information, to let the player choose whether to change their plans. For example, if the player has commanded a unit to move from (1,1) to (3,3) and attack a unit on (4,4); then a [cancel_action] inside an '''enter_hex''' [event] on (2,2) would make the unit stop on (2,2). A [cancel_action] inside an enter_hex [event] on (3,3) would let the player choose whether to attack.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|0}}&lt;br /&gt;
In a '''capture'''/'''moveto''' [event], interrupt the attack.&lt;br /&gt;
&lt;br /&gt;
=== [heal_unit] ===&lt;br /&gt;
Heal a unit. The variable '''$heal_amount''' will be set to the exact number of points healed (i.e can be less than the parameter '''amount''' if the unit is fully healed). $heal_amount contains only the number of hitpoints the first unit that was found got healed. When the variable is not needed, use {CLEAR_VARIABLE heal_amount} after this tag.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|0}} The '''$heal_amount''' variable is no longer set. Use the '''variable''' key instead.&lt;br /&gt;
*  '''[filter]''': [[StandardUnitFilter]] All matching on-map units are healed. If no filter is supplied, it is tried to take the unit at $x1, $y1.&lt;br /&gt;
*  '''[filter_second]''': [[StandardUnitFilter]] all the units matching the filter ''and'' having the ''heals'' ability will have their animation played (if ''animate'' is set to yes) for each of the units healed.&lt;br /&gt;
*  '''amount''': (integer, default full) the maximum points the unit(s) will be healed. This can't be used to set the unit's hitpoints below 1 or above the unit's maximum hitpoints. If &amp;quot;full&amp;quot;, it fully heals the unit.&lt;br /&gt;
*  '''animate''': a boolean which indicate if the healing animations must be played. (default no)&lt;br /&gt;
*  '''moves''': (integer, default 0) The maximum current movement points the units will be &amp;quot;healed&amp;quot;. Can't set below 0 or above max_moves. If &amp;quot;full&amp;quot;, sets moves to max_moves.&lt;br /&gt;
* '''restore_attacks''': (boolean, default no) Whether the units' attacks_left should be reset to their max_attacks (usually 1).&lt;br /&gt;
* '''restore_statuses''': (boolean, default yes) Whether standard statuses should be reset to &amp;quot;no&amp;quot;. This affects poisoned, slowed, petrified and unhealable.&lt;br /&gt;
* '''variable''': {{DevFeature1.17|0}} creates an array with the given name; each item of the array has two fields, ''id='' (the ID of the unit being healed) and ''heal_amount='' (the amount of HPs the unit has been healed by).&lt;br /&gt;
&lt;br /&gt;
=== [harm_unit] ===&lt;br /&gt;
Harms every unit matching the filter, for the specific damage amount. When harming multiple units, the special variable '''$this_unit''' can be used to access the current unit being harmed. This obviously does not work inside the filters though, as they give '''$this_unit''' a different meaning.&lt;br /&gt;
*  '''[filter]''': [[StandardUnitFilter]] all matching units will be harmed (required).&lt;br /&gt;
*  '''[filter_second]''': [[StandardUnitFilter]] if present, the first matching unit will attack all the units matching the filter above.&lt;br /&gt;
*  '''amount''': the amount of damage that will be done (required).&lt;br /&gt;
*  '''alignment''': (default neutral) applies an alignment to the damage, this means that if alignment=chaotic, the damage will be increased at night and reduced at day.&lt;br /&gt;
*  '''damage_type''': if present, amount will be altered by unit resistance to the damage type specified.&lt;br /&gt;
*  '''kill''': (default yes) if yes, when a harmed unit goes to or below 0 HP, it is killed; if no its HP are set to 1.&lt;br /&gt;
*  '''fire_event''': (default no) if yes, when a unit is killed by harming, the corresponding events are fired.  If yes, also the corresponding advance and post advance events are fired.&lt;br /&gt;
*  '''animate''': (default no) if yes, scrolls to each unit before harming it and plays its defense (or attack, if it's the harmer) and death animations. Special values supported, other than the usual yes and no, are &amp;quot;attacker&amp;quot;, that means only the harmer will be animated, and &amp;quot;defender&amp;quot;, that means only the harmed units will be animated. If the supplied value is yes, attacker or defender also advancement animations are played.&lt;br /&gt;
*  '''[primary_attack], [secondary_attack]''': these set the weapon against which the harmed units will defend, and that the harming unit will use to attack, respectively (notice this is the opposite of '''[filter]''' and '''[filter_second]''' above). This allows for playing specific defense and attack animations. Both tags are expected to contain a [[FilterWML#Filtering_Weapons|Standard Weapon Filter]].&lt;br /&gt;
*  '''delay''': if animate=yes, sets the delay (in milliseconds, default 500) between each unit harming.&lt;br /&gt;
*  '''variable''': if present, the damage caused to the unit, altered by resistances, will be stored in a WML array with the given name, under the ''harm_amount='' key. {{DevFeature1.17|0}} Each item of the array also has an ''id='' key, which contains the ID of the unit being harmed.&lt;br /&gt;
*  '''poisoned, slowed, petrified, unhealable''': (default no) if yes, every harmed unit that doesn't already have such status will have it set.&lt;br /&gt;
*  '''experience''': (default yes) If there is a harmer, experience will be attributed similar to regular combat. Can take list of values. When any value is provided, all unspecified experience types default to not giving experience. Supported values: {{DevFeature1.17|25}} until that version only experience=yes and experience=no are supported&lt;br /&gt;
** no - none of involved units get any experience (this value only works if it is the only value in list)&lt;br /&gt;
** kill - the harming unit receives experience based on level of harmed unit in attack which kills harmed unit&lt;br /&gt;
** attack - the harming unit receives experience based on level of harmed unit in attack which does not kill harmed unit, or in attack which kills harmed unit while kill experience is disabled&lt;br /&gt;
** defend - the unit being harmed receives experience based on level of harming unit in attack which does not kill harmed unit&lt;br /&gt;
** fight - short form of experience=attack,defend&lt;br /&gt;
** yes - short form of experience=kill,attack,defend&lt;br /&gt;
*  '''resistance_multiplier''': the harmed unit's resistance is multiplied by the supplied value; this means that a value lower than 1 increases it, and a value greater than 1 decreases it. Default value is 1, that means no modification.&lt;br /&gt;
&lt;br /&gt;
=== [time_area] ===&lt;br /&gt;
How a day should progress in a given area. Everywhere not specified in a [time_area] tag is affected by the [time] tags in the [scenario] tag.&lt;br /&gt;
* [[StandardLocationFilter]]: the locations to affect. ''note: only for [event][time_area]s - at scenario toplevel [time_area] does not support [[StandardLocationFilter]], only location ranges''&lt;br /&gt;
* '''[time]''': one or more tags describing the new schedule, see [[TimeWML]].&lt;br /&gt;
* '''id''': an unique identifier assigned to a time_area. Optional, unless you want to remove the time_area later or reference it from a location filter elsewhere. Can be a comma-separated list when removing time_areas, see below.&lt;br /&gt;
* '''remove''': (boolean) yes/no value. Indicates whether the specified time_area should be removed. Requires an identifier. If no identifier is used, however, all time_areas are removed.&lt;br /&gt;
* '''current_time''': The time slot number (starting with zero) active at the creation of the area.&lt;br /&gt;
&lt;br /&gt;
''Example:'' (caves in parts of a map)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[time_area]&lt;br /&gt;
    id = cave_area&lt;br /&gt;
    x = 1-2,4-5&lt;br /&gt;
    y = 1-2,1-2&lt;br /&gt;
    {UNDERGROUND}&lt;br /&gt;
[/time_area]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specifying an id allows the area to be referenced from location filters. Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [time_area]&lt;br /&gt;
        id = glyphs&lt;br /&gt;
        x = 9,14&lt;br /&gt;
        y = 11,3&lt;br /&gt;
    [/time_area]&lt;br /&gt;
    [event]&lt;br /&gt;
        name = moveto&lt;br /&gt;
        first_time_only=no&lt;br /&gt;
        [filter]&lt;br /&gt;
            side = 1&lt;br /&gt;
            [filter_location]&lt;br /&gt;
                area = glyphs&lt;br /&gt;
            [/filter_location]&lt;br /&gt;
        [/filter]&lt;br /&gt;
        # Do something, for example healing the unit&lt;br /&gt;
    [/event]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [remove_time_area] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|2}}&lt;br /&gt;
&lt;br /&gt;
This is a syntactic shortcut for [time_area] remove=.&lt;br /&gt;
* '''id''': Comma-separated list of time area ids to remove.&lt;br /&gt;
&lt;br /&gt;
=== [end_turn] ===&lt;br /&gt;
End the current side's turn. The current event is finished before the turn is ended. Also, if the current event (where the tag appears) has been fired by another event, that event (and the complete stack of other possible parent events) is ended before [end_turn] comes into affect. Also, events following the event stack that fired [end_turn] are not omitted (e.g. [end_turn] is used by a side turn event and a turn refresh event does something afterwards).&lt;br /&gt;
&lt;br /&gt;
=== [replace_map] ===&lt;br /&gt;
&lt;br /&gt;
Replaces the entire map.&lt;br /&gt;
* '''map_data''': Content of a wesnoth map file. (This key used to be just '''map='''.) Example:&lt;br /&gt;
 map_data=&amp;quot;{campaigns/Heir_To_The_Throne/maps/01_The_Elves_Besieged.map}&amp;quot;&lt;br /&gt;
* '''map_file''': {{DevFeature1.13|?}} Path to a Wesnoth map file; can be used instead of '''map'''. The file will be loaded when the tag is executed, rather than being embedded wholesale in the preprocessed WML. Example:&lt;br /&gt;
 map_file=campaigns/Heir_To_The_Throne/maps/01_The_Elves_Besieged.map&lt;br /&gt;
{{DevFeature1.15|3}} If the file is not found directly, it will be searched for in the [[BinaryPathWML|[binary_path]]]. Assuming a standard campaign or add-on layout, the example above can be replaced by:&lt;br /&gt;
 map_file=01_The_Elves_Besieged.map&lt;br /&gt;
* '''expand''': if 'yes', allows the map size to increase. The expansion direction is currently always bottom-right.&lt;br /&gt;
* '''shrink''': if 'yes', allows the map size to decrease. If the map size is reduced, any units that would no longer be on the map due to its coordinates no longer existing will be put into the recall list.&lt;br /&gt;
Note: When a hex changes from a village terrain to a non-village terrain, and a team owned that village it loses that village. When a hex changes from a non-village terrain to a village terrain and there is a unit on that hex it does not automatically capture the village. The reason for not capturing villages it that there are too many choices to make; should a unit lose its movement points, should capture events be fired. It is easier to do this as wanted by the author in WML.&lt;br /&gt;
&lt;br /&gt;
=== [replace_schedule] ===&lt;br /&gt;
Replace the time of day schedule of the entire scenario.&lt;br /&gt;
* [[TimeWML]]: the new schedule.&lt;br /&gt;
* '''current_time''': The time slot number (starting with zero) active at schedule replacement. ('''NB''': due to https://github.com/wesnoth/wesnoth/issues/5757 this attribute is ignored in versions 1.16.*. The fix was delivered in 1.17.* but wasn't backported due to backward-compatibility requirements)&lt;br /&gt;
&lt;br /&gt;
=== [tunnel] ===&lt;br /&gt;
&lt;br /&gt;
Create a tunnel between some locations, later usable by units to move from source hex to target hex (using the movement cost of unit on the target terrain).&lt;br /&gt;
&lt;br /&gt;
'''Behavior Change as of Wesnoth 1.13.6:''' Vision is now possible (and enabled by default) through tunnels and allied units on the exit hex do not block a tunnel by default any more. This is done in order for moves through tunnels to be consistent with other moves. The previous behavior can still be accomplished by using the new optional keys listed below.&lt;br /&gt;
&lt;br /&gt;
* '''[filter]''': (required) [[StandardUnitFilter]] the units which can use the tunnel. Leave empty for &amp;quot;all units&amp;quot;.&lt;br /&gt;
* '''[source]''': (required) [[StandardLocationFilter]] the source hex(es). Use $teleport_unit to filter on unit being teleported.&lt;br /&gt;
* '''[target]''': (required) [[StandardLocationFilter]] the target hex(es). Use $teleport_unit to filter on unit being teleported.&lt;br /&gt;
* '''id''': (optional) identifier for the tunnel, to allow removing.&lt;br /&gt;
* '''remove''': (boolean, default: no)  If yes, removes all defined tunnels with the same ID (then only id= is necessary).&lt;br /&gt;
* '''bidirectional''': (boolean, default: yes) If yes, creates also a tunnel in the other direction. &lt;br /&gt;
* '''always_visible''': (boolean, default: no) If yes, the possible movement of enemies under fog can be seen.&lt;br /&gt;
* '''allow_vision''': (boolean, default: yes) {{DevFeature1.13|6}} If no, vision through a tunnel is not possible. Note that in that case the tunnel cannot be used if the tunnel exit is under shroud (which previously was ''always'' the case).&lt;br /&gt;
* '''pass_allied_units''': (boolean, default: yes) {{DevFeature1.13|6}} If no, allied (including own) units on the exit hex block a tunnel.&lt;br /&gt;
* '''delayed_variable_substitution''' (boolean, default: yes): If yes, the WML block contained in this [tunnel] is not variable-substituted at execution time of the event where this [tunnel] is within. Instead, variables are substituted when the tunnel is used by a unit. See [[EventWML#Nested_Events]]&lt;br /&gt;
&lt;br /&gt;
(Note: The tunnel tag can also be used inside the [[AbilitiesWML|[teleport]]] ability, without remove= and id=).&lt;br /&gt;
&lt;br /&gt;
=== [do_command] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|0}}&lt;br /&gt;
&lt;br /&gt;
Executes a command, specified using the same syntax as a [command] tag in [[ReplayWML]]. Not all [command]'s are valid: only these are accepted&lt;br /&gt;
&lt;br /&gt;
* [attack]&lt;br /&gt;
* [move]&lt;br /&gt;
* [recruit]&lt;br /&gt;
* [recall]&lt;br /&gt;
* [disband]&lt;br /&gt;
* [fire_event]&lt;br /&gt;
* [lua_ai] {{DevFeature1.13|12}} This has been removed and is replaced with [custom_command]&lt;br /&gt;
&lt;br /&gt;
The tags corresponding to player actions generally use the same codepath as if a player had ordered it. That means for example that only moves that player would be allowed to do are possible, and movement is interrupted when sighting enemy unit.&lt;br /&gt;
&lt;br /&gt;
One purpose of this tag is to allow scripting of noninteractive scenarios -- without a tag like this, this might require elaborate mechanisms to coerce ais in order to test these code paths.&lt;br /&gt;
&lt;br /&gt;
This command should be replay safe if it is either invoked in a synced context, ''or'' invoked in code that is never synced, like AI code, a select event, or a menu item with `synced = false`. However, if you use desynchronized logic ''during'' an event that is otherwise synced, invoking [do_command] based on that desynchronized logic will result in out-of-sync errors during the replay; in this case, you must explicitly synchronize which command to do using something like the lua function wesnoth.sync.evaluate_single.&lt;br /&gt;
&lt;br /&gt;
=== [put_to_recall_list] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.13|0}}&lt;br /&gt;
&lt;br /&gt;
Puts a unit to the recall list of its side.&lt;br /&gt;
* '''[[StandardUnitFilter]]''': the unit(s) to get put to the recall list.&lt;br /&gt;
* '''heal''': (default=no) Whether the unit should be refreshed, similar to the unit moving to the recall list at the end of a scenario.&lt;br /&gt;
&lt;br /&gt;
=== [set_achievement] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|13}}&lt;br /&gt;
&lt;br /&gt;
Sets the specified achievement as completed and shows a popup stating it's been completed. The popup is not shown if the achievement has already been achieved.&lt;br /&gt;
&lt;br /&gt;
* '''content_for''': The [[AchievementsWML#.5Bachievement_group.5D|[achievement_group]]] that this achievement is part of.&lt;br /&gt;
* '''id''': The id of the achievement.&lt;br /&gt;
&lt;br /&gt;
=== [set_sub_achievement] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|17}}&lt;br /&gt;
&lt;br /&gt;
Sets the specified sub-achievement as completed.&lt;br /&gt;
&lt;br /&gt;
* '''content_for''': The [[AchievementsWML#.5Bachievement_group.5D|[achievement_group]]] that this achievement is part of.&lt;br /&gt;
* '''id''': The id of the achievement.&lt;br /&gt;
* '''sub_id''': The id of the sub-achievement.&lt;br /&gt;
&lt;br /&gt;
=== [progress_achievement] ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|13}}&lt;br /&gt;
&lt;br /&gt;
Progress an achievement by the specified amount, with an optional limit for how far the achievement can be progressed.&lt;br /&gt;
&lt;br /&gt;
* '''content_for''': The [[AchievementsWML#.5Bachievement_group.5D|[achievement_group]]] that this achievement is part of.&lt;br /&gt;
* '''id''': The id of the achievement.&lt;br /&gt;
* '''amount''': The amount to increment the achievement.&lt;br /&gt;
* '''limit''': (optional) Using this attribute will prevent achievements from progressing past this value.&lt;br /&gt;
&lt;br /&gt;
== Useful Macros ==&lt;br /&gt;
There are some predefined macros that you find useful for direct actions. You can find a complete list along with a detailed explanation of how they work [https://www.wesnoth.org/macro-reference.html here].&lt;br /&gt;
* '''{MOVE_UNIT}''': Moves a unit to another location in the map and the player sees the movement (unlike [teleport])&lt;br /&gt;
* '''{FULL_HEAL}''': Brings a unit to full HP&lt;br /&gt;
* '''{LOYAL_UNIT}''': Create a loyal unit&lt;br /&gt;
* '''{MODIFY_TERRAIN_MASK}''': Modify an area of terrain&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[InternalActionsWML]]&lt;br /&gt;
* [[InterfaceActionsWML]]&lt;br /&gt;
* [[EventWML]]&lt;br /&gt;
* [[ReferenceWML]]&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: ActionsWML]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/wesnoth&amp;diff=73953</id>
		<title>LuaAPI/wesnoth</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/wesnoth&amp;diff=73953"/>
		<updated>2024-11-06T23:38:20Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* wesnoth.simulate_combat */  - Document weapon evaluation table values&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;wesnoth&amp;lt;/tt&amp;gt; module contains most of the core Wesnoth API. It is always loaded and available.&lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.dofile ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.dofile'''(''file_path'', [...]) &amp;amp;rarr; ...&lt;br /&gt;
&lt;br /&gt;
Loads and executes a file. The rules for locating the files are the same as for WML files, except that they require a ''.lua'' extension instead of ''.cfg.'' Any extra parameters to '''dofile''' are forwarded to the script (which can access them via the special &amp;lt;tt&amp;gt;...&amp;lt;/tt&amp;gt; variable), and '''dofile''' returns all the values returned by the script.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.require ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.require'''(''module'') &amp;amp;rarr; ''module_contents''&lt;br /&gt;
&lt;br /&gt;
Returns the contents of the specified module, loading it if necessary. The module can either be a simple name or a file path similar to that used by '''wesnoth.dofile'''. In addition, the ''.lua'' extension will automatically be appended if necessary. The module script is invoked with no arguments, and '''wesnoth.require''' then passes back its first return value, discarding any additional ones. If the module is a directory, then all lua files are loaded, and a table containing the resulting modules is returned, with the keys being the filenames minus the ''.lua'' extension.&lt;br /&gt;
&lt;br /&gt;
'''wesnoth.require''' returns nil on failure, for example if it could not locate the module. If it did locate the module, but the module did not return anything (or returned nil), then '''wesnoth.require''' returns an empty table with a metatable that raises an error on any attempt to access it.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.textdomain ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.textdomain'''(''domain'') &amp;amp;rarr; ''textdomain_constructor''&lt;br /&gt;
&lt;br /&gt;
Returns a callable userdata that can be used to construct translatable strings. A typical use is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local _ = wesnoth.textdomain &amp;quot;example&amp;quot;&lt;br /&gt;
wesnoth.alert(_ &amp;quot;This is an example translated string!&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full syntax for using the result of this function is:&lt;br /&gt;
&lt;br /&gt;
* ''textdomain_constructor''(''string'', [''string_plural'', ''number'']) &amp;amp;rarr; ''translatable_string''&lt;br /&gt;
&lt;br /&gt;
By passing the optional arguments, you can vary the string based on a number that will be substituted into it. As with all Lua functions, the parentheses are optional when passing a single string argument, as in the above example. This plural syntax returns a form of the string that's grammatically suitable for the indicated number, but doesn't actually substitute the number in – you need to do that yourself with either '''string.format''' or '''stringx.vformat'''.&lt;br /&gt;
&lt;br /&gt;
The returned translatable string can be treated in many ways like a regular string. Translatable strings can be compared with other translatable strings or concatenated with each other or with regular strings or integers. The length operator also works, though it should be noted that its value may change if the language is changed. If you need to pass a translatable string to a function that doesn't understand them, it can be converted to a regular string with tostring.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.log ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.log'''([''logger''], ''message'', ''in_chat'')&lt;br /&gt;
&lt;br /&gt;
Logs a message to the console. These messages are normally not visible unless Wesnoth is run from the command-line or (in Windows) with the --wconsole switch. The in_chat argument, however, can be set to true to also echo the message to the in-game chat area.&lt;br /&gt;
&lt;br /&gt;
''logger'' is the log level.&lt;br /&gt;
&lt;br /&gt;
In any context, ''logger'' can be the standard log levels of '''info''', '''debug''', '''warning''', or '''error'''. Various abbreviations of the standard four are also recognised. The default logger is '''info'''.&lt;br /&gt;
&lt;br /&gt;
In the game context, you can also set the ''logger'' to '''wml'''. The '''wml''' log level is special and is intended for WML errors; it always goes to chat, so the in_chat argument is ignored and can be omitted.&lt;br /&gt;
&lt;br /&gt;
The logdomain to enable these logs depends on the context. In the game context, they are written to the '''wml''' logdomain. In other contexts, the logdomain is '''scripting/lua/user'''.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.as_text ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|10}}&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.as_text'''(''value1'', ''value2'', ...)&lt;br /&gt;
&lt;br /&gt;
Accept one or more values as arguments and returns them as a string.  This is intended for use as an easy way to view the contents of lua tables.  Using the returned string for any other purpose is not supported.&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|0}} This is now available in all contexts.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.simulate_combat ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.simulate_combat'''(''attacker'', [''attacker_weapon_index''], ''defender'', [''defender_weapon_index'']) &amp;amp;rarr; ''attacker stats evaluation'', ''defender stats evaluation'', ''attacker weapon evaluation'', ''defender weapon evaluation''&lt;br /&gt;
&lt;br /&gt;
Computes the hitpoint distribution and status chance after a combat between two units.  The first unit is the attacker. The attacker does not have to be on the map, but its location should be meaningful - that is, it can be a private-to-Lua clone of a unit with the '''x''' and '''y''' values changed, but whatever it is it has to have '''x''' and '''y''' values that allow attacking the defender (with '''max_range''' of the attack set appropriately it's possible to simulate attacking non-adjacent units). The second unit is the defender; it has to be on the map.&lt;br /&gt;
&lt;br /&gt;
Optional integers can be passed after each unit to select a particular weapon, otherwise the &amp;quot;best&amp;quot; one is selected.  When giving the weapon, the parameter is the weapon number (integer, starting at 1) and not the attack definition.&lt;br /&gt;
&lt;br /&gt;
The function returns four tables describing the evaluation of the combat. The first two contain an evaluation of the combatant's stats over the course of the fight, while the second two contains more detailed information on their weapons.&lt;br /&gt;
&lt;br /&gt;
The stats evaluation tables contain the following keys:&lt;br /&gt;
&lt;br /&gt;
* ''stats''.'''poisoned''' &amp;amp;rarr; ''probability''&lt;br /&gt;
* ''stats''.'''slowed''' &amp;amp;rarr; ''probability''&lt;br /&gt;
* ''stats''.'''untouched''' &amp;amp;rarr; ''probability''&lt;br /&gt;
&lt;br /&gt;
The probability that the unit will be poisoned or slowed, or that it will survive with no damage taken. (A scenario where the unit's hitpoints increase counts as untouched.)&lt;br /&gt;
&lt;br /&gt;
* ''stats''.'''average_hp''' &amp;amp;rarr; ''number''&lt;br /&gt;
&lt;br /&gt;
The expected value of the unit's hitpoints after the fight.&lt;br /&gt;
&lt;br /&gt;
* ''stats''.'''hp_chance''' &amp;amp;rarr; ''mapping of hp to probability''&lt;br /&gt;
&lt;br /&gt;
The probability that the unit's hitpoints will be at a specific value after the fight. Though it looks almost like an array, it begins at index 0 unlike a typical Lua array. Thus, it's better understood as an associated mapping from the resulting hitpoints value to the probability of ending the combat with that value. Therefore, the value at index 0 represents the chance that the unit will die.&lt;br /&gt;
&lt;br /&gt;
The weapon evaluation tables contain the following keys:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Key !!Description&lt;br /&gt;
|-&lt;br /&gt;
|attack_num&lt;br /&gt;
| DEPRECATED (use '''number''').  Attack number (0 based, -1 for no attack).&lt;br /&gt;
|-&lt;br /&gt;
|chance_to_hit&lt;br /&gt;
|Effective chance to hit as a percentage (all factors accounted for). &lt;br /&gt;
|-&lt;br /&gt;
|damage&lt;br /&gt;
|Effective damage of the weapon (all factors accounted for).&lt;br /&gt;
|-&lt;br /&gt;
|drains&lt;br /&gt;
|Attack [[AbilitiesWML#The_.5Bspecials.5D_tag|drains]] opponent when it hits.&lt;br /&gt;
|-&lt;br /&gt;
|drain_constant&lt;br /&gt;
|Base HP drained regardless of damage dealt.&lt;br /&gt;
|-&lt;br /&gt;
|drain_percent&lt;br /&gt;
|Percentage of damage recovered as health.&lt;br /&gt;
|-&lt;br /&gt;
|firststrike&lt;br /&gt;
|Attack has [[AbilitiesWML#The_.5Bspecials.5D_tag|firststrike]] special.&lt;br /&gt;
|-&lt;br /&gt;
|name&lt;br /&gt;
|Name (not description) of the attack.&lt;br /&gt;
|-&lt;br /&gt;
|number&lt;br /&gt;
|Attack number (1 based, 0 for no attack).&lt;br /&gt;
|-&lt;br /&gt;
|num_blows&lt;br /&gt;
|Effective number of blows (takes [[AbilitiesWML#The_.5Bspecials.5D_tag|swarm]] into account).&lt;br /&gt;
|-&lt;br /&gt;
|petrifies&lt;br /&gt;
|Attack [[AbilitiesWML#The_.5Bspecials.5D_tag|petrifies]] opponent when it hits. &lt;br /&gt;
|-&lt;br /&gt;
|plagues&lt;br /&gt;
|Attack [[AbilitiesWML#The_.5Bspecials.5D_tag|turns opponent into a zombie]] when fatal.&lt;br /&gt;
|-&lt;br /&gt;
|plague_type&lt;br /&gt;
|The [[AbilitiesWML#Extra_keys_used_by_the_.5Bplague.5D_special|plague type]] used by the attack, if any.&lt;br /&gt;
|-&lt;br /&gt;
|poisons&lt;br /&gt;
|Attack [[AbilitiesWML#The_.5Bspecials.5D_tag|poisons]] opponent when it hits.&lt;br /&gt;
|-&lt;br /&gt;
|rounds&lt;br /&gt;
|[[AbilitiesWML#The_.5Bspecials.5D_tag|Berserk]] special can force us to fight more than one round.&lt;br /&gt;
|-&lt;br /&gt;
|slows&lt;br /&gt;
|Attack [[AbilitiesWML#The_.5Bspecials.5D_tag|slows]] opponent when it hits.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang='lua'&amp;gt;&lt;br /&gt;
local function display_stats(n, t)&lt;br /&gt;
    wesnoth.interface.add_chat_message(string.format(&lt;br /&gt;
        &amp;quot;Chance for the %s\n  to be slowed: %f,\n  to be poisoned: %f,\n  to die: %f.\nAverage HP: %f.&amp;quot;,&lt;br /&gt;
        n, t.slowed, t.poisoned, t.hp_chance[0], t.average_hp))&lt;br /&gt;
end&lt;br /&gt;
local att_stats, def_stats = wesnoth.simulate_combat(att, att_weapon, def, def_weapon)&lt;br /&gt;
display_stats(&amp;quot;attacker&amp;quot;, att_stats)&lt;br /&gt;
display_stats(&amp;quot;defender&amp;quot;, def_stats)&lt;br /&gt;
&lt;br /&gt;
local att_stats, def_stats, att_weapon, def_weapon = wesnoth.simulate_combat(attacker, att_weapon_number, defender)&lt;br /&gt;
wesnoth.interface.add_chat_message(string.format(&lt;br /&gt;
    &amp;quot;The attack %s should be countered with %s, which does %d damage, has %d%% chance to hit and forces %d attack rounds due to its berserk ability.&amp;quot;,&lt;br /&gt;
    att_weapon.name, def_weapon.name or &amp;quot;no weapon&amp;quot;, def_weapon.damage, def_weapon.chance_to_hit, def_weapon.rounds))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.name_generator ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.name_generator'''('''&amp;quot;markov&amp;quot;''', ''definition'', [''chain_size'', [''max_length'']]) &amp;amp;rarr; ''generator function''&lt;br /&gt;
* '''wesnoth.name_generator'''('''&amp;quot;cfg&amp;quot;''', ''definition'') &amp;amp;rarr; ''generator function''&lt;br /&gt;
* ''generator function''() &amp;amp;rarr; ''random name''&lt;br /&gt;
&lt;br /&gt;
Constructs a name generator for use in generating names using either the Markov chain algorithm used in older versions of Wesnoth or the context-free grammar generator used since 1.13.5. The type parameter indicates which algorithm to use (either markov or cfg). The definition can be a string, just like it would be in a config file, or it can be formatted as a table. Additional parameters may be passed, depending on the type of generator. The function returns a callable userdata, which will return a new name each time it is called (with no parameters).&lt;br /&gt;
&lt;br /&gt;
* '''Markov chain''': A Markov chain generator works by analyzing a list of input names and noticing tendencies in the way the letters are strung together. It can then apply those tendencies to produce new similar names that were not in the original list. Longer lists give better results. The definition is a list of names, formatted either as a comma-separated string or as an array-like table. The Markov generator can take two additional parameters.&lt;br /&gt;
** ''chain_size'': A value greater than 1 for the ''chain_size'' causes the analyzer to consider the words in chunks, which is similar to analyzing them syllable by syllable instead of letter by letter. The default chain size is 2, meaning that the analyzer treats words as consisting of 2-character syllables.&lt;br /&gt;
** ''max_length'': Places a cap on the total length of the name. The default value is 12 characters.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local markov_names = wesnoth.name_generator('markov', {'Kaasa', 'Kayya', 'Keyya', 'Kiira', 'Korra'}, 1)&lt;br /&gt;
print(markov_names(), markov_names(), markov_names())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* '''Context-free grammar''': A [[context-free grammar]] is a way of specifying how strings can be constructed. The definition may be specified as a multi-line string, just as described in the preceding link, or it can be formatted as a table where the keys are non-terminals and the values are what they expand to. The expansion of each non-terminal can be formatted either as a |-separated list as described in the preceding link, or as an array-like table. (Mixing the two forms is permissible too.) The context-free generator has no additional parameters.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local cfg_names = wesnoth.name_generator('cfg', {&lt;br /&gt;
  main = {'{prefix}{suffix}', '{prefix}{centre}{suffix}'},&lt;br /&gt;
  prefix = 'Kaa|Ka|Ke|Kuu|Ko',&lt;br /&gt;
  suffix = 'sa|yya|ra|rra',&lt;br /&gt;
  centre = 'err|aash|eez|azz'&lt;br /&gt;
})&lt;br /&gt;
print(cfg_names(), cfg_names(), cfg_names())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': If you want to generate a name using any of the default generators, you can use the predefined generators in the [[LuaAPI/types#race|race]] instead of constructing one with this function.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.compile_formula ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.compile_formula'''(''formula'') &amp;amp;rarr; ''compiled formula''&lt;br /&gt;
&lt;br /&gt;
Compiles a [[Wesnoth Formula Language]] formula into a Lua callable userdata. A compiled formula can be converted back to valid code using the built-in &amp;lt;code&amp;gt;tostring&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.eval_formula ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.eval_formula'''(''formula'', [''variables'']) &amp;amp;rarr; ''result''&lt;br /&gt;
* ''compiled formula''([''variables'']) &amp;amp;rarr; ''result''&lt;br /&gt;
&lt;br /&gt;
Evaluate a [[Wesnoth Formula Language]] formula and return the result it computed (which can be '''nil''').&lt;br /&gt;
&lt;br /&gt;
The passed in variables can be an arbitrary Lua table, which defines variables available to the formula. Unlike with WML tables, there is no restriction on the format of this table. The formula can access the variables as a list using the special WFL variable '''__list''', or as a map using the special WFL variable '''__map'''. Directly accessing keys on the table is also possible.&lt;br /&gt;
&lt;br /&gt;
It is also possible to pass a unit proxy as the variables, which evaluates the formula in that unit's context just as if it had been used in a [[StandardUnitFilter]].&lt;br /&gt;
&lt;br /&gt;
When calling '''wesnoth.eval_formula''', the first argument may either be an already-compiled formula or a string, in which case it will be automatically compiled on the fly.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local f = wesnoth.compile_formula('if(x &amp;gt; y, x - y, x + y)')&lt;br /&gt;
&lt;br /&gt;
print(f{x=1,y=2}) -- prints 3.0&lt;br /&gt;
print(f{x=1,y=3}) -- prints 4.0&lt;br /&gt;
print(f{x=2,y=3}) -- prints 5.0&lt;br /&gt;
print(f{x=1,y=1}) -- prints 2.0&lt;br /&gt;
print(f{x=3,y=1}) -- prints 2.0&lt;br /&gt;
print(f{x=3,y=2}) -- prints 1.0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.version ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.version'''(''version string'') &amp;amp;rarr; ''version''&lt;br /&gt;
* '''wesnoth.version'''(''major'', [''minor'', [''patch'']], [''suffix'')) &amp;amp;rarr; ''version''&lt;br /&gt;
&lt;br /&gt;
Creates a version object, either by parsing a string or by building it from its component parts. The resulting version object can be compared with other version objects using the standard Lua comparison operators, which follows the same rules as the [[PreprocessorRef#.23ifver_and_.23ifnver|#ifver]] preprocessor statement. It can also be decomposed by accessing the following keys on the object:&lt;br /&gt;
&lt;br /&gt;
* ''integer'': Grab any integer version component by index. A non-canonical version may have more than three components.&lt;br /&gt;
* '''major''': The major version number (index 1).&lt;br /&gt;
* '''minor''': The minor version number (index 2).&lt;br /&gt;
* '''revision''': The patch revision number (index 3).&lt;br /&gt;
* '''is_canonical''': True if the version has at most three components (plus an optional suffix).&lt;br /&gt;
* '''sep''': The character that separates the version components from the suffix (usually either + or nil).&lt;br /&gt;
* '''special''': The version suffix, for example the &amp;quot;dev&amp;quot; in &amp;quot;1.15.14+dev&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The version can be converted to a string using the built-in '''tostring''' function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function version_is_sufficient(required)&lt;br /&gt;
  return wesnoth.current_version() &amp;gt;= required&lt;br /&gt;
end&lt;br /&gt;
local required = wesnoth.version &amp;quot;1.9.6&amp;quot;&lt;br /&gt;
if not version_is_sufficient(required) then&lt;br /&gt;
  gui.alert(string.format(&amp;quot;Your BfW version is insufficient, please get BfW %s or greater!&amp;quot;, tostring(required)))&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.current_version ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.current_version'''() &amp;amp;rarr; ''current version''&lt;br /&gt;
&lt;br /&gt;
Returns the current version of Wesnoth as a version object.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.ms_since_init ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.ms_since_init'''() &amp;amp;rarr; ''milliseconds''&lt;br /&gt;
&lt;br /&gt;
This function returns the amount of milliseconds that have passed since Wesnoth started up the current session. Its only use is to track the passage of real time.&lt;br /&gt;
&lt;br /&gt;
'''WARNING:''' this function uses the same code as [set_variable] time=stamp, and so it is MP-unsafe. It is provided only for benchmark purposes and AI development, although it should work inside wesnoth.synchronize_choice() as well.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.deprecated_message ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.deprecated_message'''(''element_name'', ''level'', ''version'', ''detail_message'')&lt;br /&gt;
&lt;br /&gt;
Displays a deprecation warning in the Lua console. The level is an integer from 1 to 4 inclusive (see [[CompatibilityStandards#Deprecation_levels_-_When_to_remove_deprecated_features|deprecation levels]]), and the version can be left nil for levels 1 and 4. Otherwise it must be a version ''string'' (not a version object from [[#wesnoth.version|wesnoth.version]]).&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.deprecate_api ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.deprecate_api'''(''original_name'', ''new_name'', ''level'', ''version'', ''element'', ''detail_message'') &amp;amp;rarr; ''deprecated wrapper''&lt;br /&gt;
&lt;br /&gt;
Creates a deprecated wrapper for a function or table. A deprecated function will raise the deprecated message the first time it's called, and then suppress it thereafter. A deprecated table will raise the deprecated message the first time a key is read or assigned, and then suppress it thereafter.&lt;br /&gt;
&lt;br /&gt;
The ''element'' is the function or table to wrap. It can be the original function or the new function (which may happen if the function was renamed without any interface changes), or a wrapper function that calls the new function while providing the interface of the old function. The ''level'' and ''version'' are as in [[#wesnoth.deprecated_message|wesnoth.deprecated_message]].&lt;br /&gt;
&lt;br /&gt;
If ''level'' is 4, then the ''element'' is ignored (you can pass '''nil''') and a generic deprecated wrapper is returned that does nothing but raises the deprecated message the first time you call it, assign a key, or read a key, and suppresses it thereafter. This is intended for a function that was removed without deprecation, to leave behind a more informative message if someone still attempts to use it.&lt;br /&gt;
&lt;br /&gt;
If Wesnoth is run with the &amp;lt;tt&amp;gt;--strict-lua&amp;lt;/tt&amp;gt; command-line option, this function will return '''nil''' instead of the deprecated wrapper. Since the normal use-case of this function is to assign the deprecated wrapper to the original name, this has the effect of erasing any deprecated functions from the API.&lt;br /&gt;
&lt;br /&gt;
The result of this function always contains a '''__deprecated''' attribute set to true, which can allow identifying if something is deprecated.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.type ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|?}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.type'''(''value'') &amp;amp;rarr; ''type name''&lt;br /&gt;
&lt;br /&gt;
Returns a string describing the value's type. This is the same as the built-in type function, except that it returns a more specific string in the case of userdata or tables, based on the metatable. For example, it would return 'unit' if called on a unit.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.named_tuple ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|?}}&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.named_tuple'''(''array'', ''names'') &amp;amp;rarr; ''named tuple''&lt;br /&gt;
&lt;br /&gt;
Decorates a numeric based array so that the indices can be accessed by name instead of by index. This function is used internally for a number of things, most notably map locations and WML tags. Most end-users will not need to use it, but it could be useful if you wish to build a Lua API that returns locations (or similar data) in the engine-standard format.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local t = wesnoth.named_tuple({42,21,36}, {'x', 'y', 'z'})&lt;br /&gt;
&lt;br /&gt;
print(t[1]) -- prints 42&lt;br /&gt;
print(t[2]) -- prints 21&lt;br /&gt;
print(t[3]) -- prints 36&lt;br /&gt;
print(t.x) -- prints 42&lt;br /&gt;
print(t.y) -- prints 21&lt;br /&gt;
print(t.z) -- prints 36&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.get_language ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.get_language'''() &amp;amp;rarr; ''string''&lt;br /&gt;
&lt;br /&gt;
Gets the language the UI is currently set to. Note that this may return an empty string if using the system default language.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.print_attributes ===&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.print_attributes'''(''object'', [''function''])&lt;br /&gt;
&lt;br /&gt;
Prints out a list of attributes that can be accessed on the object, excluding deprecated functionality. The function defaults to '''print''', and receives a formatted line usually containing multiple attributes. They are annotated by type – &amp;amp;fnof; for a function, &amp;amp;dagger; for a table, ! if there was an error attempting to determine the type (which includes write-only attributes). Other types are unannotated.&lt;br /&gt;
&lt;br /&gt;
For tables, by default this iterates the table using '''pairs''' to discover the attributes available, walking the metatable hierarchy if there is an '''__index''' table and filtering out anything that contains a '''__deprecated''' attribute set to '''true'''. However, if finds a function as the '''__index''', and the table's metatable also has a member '''__dir''', it will be used instead. The '''__dir''' can either be an array of strings, or a function that returns an array of strings. It will automatically be sorted and have any duplicates filtered out.&lt;br /&gt;
&lt;br /&gt;
For custom objects defined by the engine, there is special handling so that this function shows the correct result. For example, if used on a GUI2 widget object, it will show the attributes available for that type of widget, as well as the IDs of any sub-widgets that can be accessed by name.&lt;br /&gt;
&lt;br /&gt;
In the Lua console only, this function can also be referenced by a shorter alias, '''dir'''.&lt;br /&gt;
&lt;br /&gt;
== Hooks ==&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.persistent_tags ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.persistent_tags'''.''action''.'''read''' &amp;amp;harr; '''function'''(''wml content'')&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.persistent_tags'''.''action''.'''write''' &amp;amp;harr; '''function'''(''add_tag_function'')&lt;br /&gt;
&lt;br /&gt;
This is an associative table defining tags that should be persisted in saved games. Each tag is itself a table containing two functions, read and write. The write function is called in &amp;lt;tt&amp;gt;on_load&amp;lt;/tt&amp;gt; and passed a function as a parameter which takes a WML table and adds it to the saved game under the specified tag; the read function is called once per matching tag found in the saved game, and is passed a WML table of its contents. Note the asymmetry here: if you're saving an array, the write function is responsible for saving the entire array (and is only called once), while the read function is only responsible for loading one item (and is called several times).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local inventory = {}&lt;br /&gt;
&lt;br /&gt;
function wesnoth.persistent_tags.inventory.read(cfg)&lt;br /&gt;
    inventory[cfg.side] = cfg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function wesnoth.persistent_tags.inventory.write(add)&lt;br /&gt;
    for i = 1, #wesnoth.sides do&lt;br /&gt;
        add(inventory[i])&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that you don't need to create &amp;lt;tt&amp;gt;wesnoth.persistent_tags.inventory&amp;lt;/tt&amp;gt; as an empty table first; you can simply define the read and write functions.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.wml_actions ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.wml_actions'''.''action'' &amp;amp;harr; '''function'''(''wml parameters table'')&lt;br /&gt;
&lt;br /&gt;
This is a hook table that exposes and defines WML actions. Each function in this table corresponds to a single ActionWML tag, allowing you to invoke tags, define custom tags, and even modify the behavior of built-in tags. The single argument to these functions is a WML table, the content of the tag.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.freeze_unit(cfg)&lt;br /&gt;
    local unit_id = cfg.id or wml.error &amp;quot;[freeze_unit] expects an id= attribute.&amp;quot;&lt;br /&gt;
    local unit = wesnoth.units.get(unit_id)&lt;br /&gt;
    if unit then unit.moves = 0 end&lt;br /&gt;
    wesnoth.units.modify({ id = unit_id }, { moves = 0 })&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new tag can now be used in plain WML code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[freeze_unit]&lt;br /&gt;
    id=Delfador&lt;br /&gt;
[/freeze_unit]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can override functions already assigned to the table. This is useful if you need to extend functionality of core tags. For instance, the following script overrides the [[InterfaceActionsWML#Other interface tags|[print]]] tag so that messages are displayed with a bigger font.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.print(cfg)&lt;br /&gt;
    local modified_cfg = setmetatable({}, {__index = cfg})&lt;br /&gt;
    modified_cfg.size = (cfg.size or 12) + 10&lt;br /&gt;
    wesnoth.wml_actions.print(modified_cfg)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An action handler should be able to handle being called with either a WML table or a WML vconfig userdata. It is recommended to pass the argument through ''wml.tovconfig'' before doing anything with it, both in the action's definition and when calling it directly (in case its definition did not do that). The engine always passes a vconfig when calling a WML action.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.wml_conditionals ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.wml_conditionals'''.''action'' &amp;amp;harr; '''function'''(''wml parameters table'') &amp;amp;rarr; ''boolean result''&lt;br /&gt;
&lt;br /&gt;
This is a hook table like wesnoth.wml_actions. You can use it to define new ConditionalWML tags that will be recognized in WML when using [if], [show_if], [while], etc., or more generally when [[../wml#wml.eval_conditional|'''wml.eval_conditional''']] is run.&lt;br /&gt;
&lt;br /&gt;
Use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_conditionals.foo(cfg)&lt;br /&gt;
    local bar = cfg.bar or wml.error(&amp;quot;[foo] tag did not have 'bar' attribute&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    return (bar == &amp;quot;baz&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this lua code is executed, it would make the following syntax be valid WML in your add-on:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[if]&lt;br /&gt;
   [foo]&lt;br /&gt;
      bar = $X&lt;br /&gt;
   [/foo]&lt;br /&gt;
   [then]&lt;br /&gt;
      [message]&lt;br /&gt;
         # ...&lt;br /&gt;
      [/message]&lt;br /&gt;
   [/then]&lt;br /&gt;
[/if]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the basic logic tags of ConditionalWML (true, false, and, or, not) do not pass through this table and cannot be overridden.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.effects ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.effects'''.''name'' &amp;amp;harr; '''function'''(''unit'', ''wml table'')&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.effects'''.''name''.'''__descr''' &amp;amp;harr; ''description''&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.effects'''.''name''.'''__descr''' &amp;amp;harr; '''function'''(''unit'', ''wml table'') &amp;amp;rarr; ''description''&lt;br /&gt;
&lt;br /&gt;
This table contains the implementation of [[EffectWML|[effect]]]s. Each value is a callable value that takes a unit and the effect config. It can be a function or a callable table. If it is a callable table, its metatable may have a '''__descr''' field which is either a string or a function. Built-in effects are present in this table, and you may register your own custom effects too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang='lua'&amp;gt;&lt;br /&gt;
function wesnoth.effects.min_resistance(u, cfg)&lt;br /&gt;
	local resistance_new = {}&lt;br /&gt;
	local resistance_old = wml.parsed(wml.get_child(cfg, &amp;quot;resistance&amp;quot;))&lt;br /&gt;
	for k,v in pairs(resistance_old) do&lt;br /&gt;
		if type(k) == &amp;quot;string&amp;quot; and type(v) == &amp;quot;number&amp;quot; and u:resistance_to(k) &amp;gt;= v then&lt;br /&gt;
			resistance_new[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	wesnoth.effects.resistance(u, {&lt;br /&gt;
		apply_to = &amp;quot;resistance&amp;quot;,&lt;br /&gt;
		replace = true,&lt;br /&gt;
		T.resistance (resistance_new),&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code above adds a new &amp;lt;code&amp;gt;min_resistance&amp;lt;/code&amp;gt; effect that will set the resistances to specific values if they are currently below that value. It can then be used like this (for example, in [[DirectActionsWML#.5Bobject.5D|[object]]]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang='wml'&amp;gt;&lt;br /&gt;
[effect]&lt;br /&gt;
  apply_to=min_resistance&lt;br /&gt;
  [resistance]&lt;br /&gt;
    cold=50&lt;br /&gt;
  [/resistance]&lt;br /&gt;
[/effect]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in order work properly, effects must be registered before any units are created. This means it must be placed into a global or scenario level [lua] tag. In particular, the preload event is too late.&lt;br /&gt;
&lt;br /&gt;
You can also specify description modifiers, which will be used if a custom effect is placed in a &amp;lt;code&amp;gt;[trait]&amp;lt;/code&amp;gt; tag. Instead of setting a function as the effect, you set a table with a &amp;lt;code&amp;gt;__call&amp;lt;/code&amp;gt; metafunction which does what the function would have done. The table can then have an additional &amp;lt;code&amp;gt;__descr&amp;lt;/code&amp;gt; metafunction which updates descriptions as necessary. The built-in effects all use this structure. This metafunction takes the same arguments as the regular effect function, but should not modify the unit. Instead, it returns a string to be appended to the trait's effect description.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.micro_ais ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.micro_ais'''.''ai_name'' &amp;amp;harr; ''function''(''cfg'') &amp;amp;rarr; ''required'', ''optional'', ''ca_params''&lt;br /&gt;
&lt;br /&gt;
Registers a new [[Micro_AIs#Custom_Micro_AIs|MicroAI]] with '''ai_type'''=''ai_name''. The function will be called by the [micro_ai] tag to set up the AI. See the link for more details on how this works.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.custom_synced_commands ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.custom_synced_commands'''.''command_name'' &amp;amp;harr; ''function''(''cfg'')&lt;br /&gt;
&lt;br /&gt;
Registers a custom synced command, which can be invoked by AI to enable unusual behaviour. The command can do basically anything, and is guaranteed to run on all clients. The WML table passed to the callback is the same table passed to [[LuaAPI/wesnoth/sync#wesnoth.sync.invoke_command|wesnoth.sync.invoke_command]].&lt;br /&gt;
&lt;br /&gt;
== Data ==&lt;br /&gt;
&lt;br /&gt;
Access to most of the game data is available via various tables in the &amp;lt;tt&amp;gt;wesnoth&amp;lt;/tt&amp;gt; module.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.colors ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|4}}&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.colors'''.''color_name'' &amp;amp;rarr; ''color info''&lt;br /&gt;
&lt;br /&gt;
Access defined [[GameConfigWML#Color_Palettes|color ranges]]. This can be used to translate the color name available from '''wesnoth.sides[n].color''' to RGB values.&lt;br /&gt;
&lt;br /&gt;
Each color info table contains the following keys:&lt;br /&gt;
&lt;br /&gt;
* '''mid''' - average shade for recoloring with the team color&lt;br /&gt;
* '''min''' - minimum shade for recoloring with the team color (this is likely to be black)&lt;br /&gt;
* '''max''' - maximum shade for recoloring with the team color (this is likely to be almost white)&lt;br /&gt;
* '''minimap''' - representative color to use on the mini-map&lt;br /&gt;
* '''pango_color''' - {{DevFeature1.15|13}} a hex string such as '''#ff0000''' suitable for use in formatted text&lt;br /&gt;
&lt;br /&gt;
Each of '''mid''', '''min''', '''max''' and '''minimap''' have the following keys:&lt;br /&gt;
&lt;br /&gt;
* '''r''' - red component of that color&lt;br /&gt;
* '''g''' - green component of that color&lt;br /&gt;
* '''b''' - blue component of that color&lt;br /&gt;
* '''a''' - alpha component of that color (probably fully opaque)&lt;br /&gt;
&lt;br /&gt;
Reference usage in mainline: see data/multiplayer/eras.lua&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.current ===&lt;br /&gt;
&lt;br /&gt;
Contains various information about the current game and event state.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.side''' &amp;amp;rarr; ''side number''&lt;br /&gt;
&lt;br /&gt;
The number of the currently active side.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.turn''' &amp;amp;rarr; ''turn number''&lt;br /&gt;
&lt;br /&gt;
The current turn number.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.synced_state''' &amp;amp;rarr; ''state''&lt;br /&gt;
&lt;br /&gt;
Allows you to determine whether the current code runs in a synced context. Returns one of the following strings:&lt;br /&gt;
&lt;br /&gt;
:* '''synced''' - The current code runs on all mp clients. This is the normal context, in which all gamestate changing actions should take place.&lt;br /&gt;
:* '''unsynced''' - The current code runs only on the local machine, so changing the gamestate here will cause out-of-sync errors. For example, during '''select''' events or during the calculation of a [[LuaAPI/wesnoth/interface#wesnoth.interface.game_display|game_display]] hook. Typical things to do here are UI related things, or entering the synced state via '''[do_command]'''.&lt;br /&gt;
:* '''local_choice''' - The current code was invoked by [[#wesnoth.synchronize_choice|synchronize_choice]] and runs only on one local client to calculate the return value for the choice. You cannot enter the synced context with '''[do_command]''' now.&lt;br /&gt;
:* '''preload''' - We are currently running a preload event or an even earlier event. This behaves similar to '''local_choice'''.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.user_can_invoke_commands''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Indicates whether the player is currently able to take actions in the game.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.map''' &amp;amp;rarr; ''map userdata''&lt;br /&gt;
&lt;br /&gt;
The current active game map. See [[LuaAPI/types/map]] and [[LuaAPI/wesnoth/map]] for information on how this data can be used.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.schedule''' &amp;amp;rarr; ''schedule userdata''&lt;br /&gt;
&lt;br /&gt;
The current global time schedule. This is a special object with the following properties:&lt;br /&gt;
&lt;br /&gt;
:* #''schedule''&lt;br /&gt;
:The Lua length operator will return the number of turns in the schedule.&lt;br /&gt;
&lt;br /&gt;
:* ''schedule''[''index''] &amp;amp;harr; ''time of day info''&lt;br /&gt;
:Get the information for a particular time of day, or replace it with new info.&lt;br /&gt;
&lt;br /&gt;
:* ''schedule''.'''time_of_day''' &amp;amp;harr; ''id''&lt;br /&gt;
:Get the ID of the current active time of day, or switch to a new one. If the time of day occurs more than once in the schedule, the time will be set to the first occurrence.&lt;br /&gt;
&lt;br /&gt;
:* ''schedule''.'''liminal_bonus''' &amp;amp;harr; ''bonus''&lt;br /&gt;
:Get the maximum bonus for liminal units in the current schedule. You can also override the default by assigning a different value, or revert to the default by assigning nil.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.current.event_context''' &amp;amp;rarr; ''WML table''&lt;br /&gt;
&lt;br /&gt;
Contains information on the current active event. Returns a table with the following keys:&lt;br /&gt;
&lt;br /&gt;
:* '''name''' - The event name. This is the actual event that fired, not the name in the [event] tag, so it never contains commas or variables.&lt;br /&gt;
:* '''id''' - The event's unique ID, if it has one.&lt;br /&gt;
:* '''weapon''' - The first weapon relevant to the event, if any.&lt;br /&gt;
:* '''second_weapon''' - The second weapon relevant to the event, if any.&lt;br /&gt;
:* '''damage_inflicted''' - The damage inflicted in the event, if applicable.&lt;br /&gt;
:* '''x1''', '''y1''' - The first location relevant to the event, if any.&lt;br /&gt;
:* '''x2''', '''y2''' - The second location relevant to the event, if any.&lt;br /&gt;
:* '''unit_x''', '''unit_y''' - The location of the first unit relevant to the event, if any. This is the same as '''x1''', '''y1''' in most cases. Currently the only exceptions are enter and exit hex events.&lt;br /&gt;
:* '''data''' - {{DevFeature1.17|6}} The event data. Can contain anything at all if the event was fired by [[LuaAPI/wesnoth/game_events#wesnoth.game_events.fire|wesnoth.game_events.fire]]. In a village capture event, '''owner_side''' will contain the former owner of the village.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.game_config ===&lt;br /&gt;
&lt;br /&gt;
Contains static global information about the game. Some of this information can also be modified on the fly, but only in the game context, not in the plugin or map generator context.&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.game_config.base_income''' &amp;amp;harr; ''integer''&lt;br /&gt;
* '''wesnoth.game_config.village_income''' &amp;amp;harr; ''integer''&lt;br /&gt;
* '''wesnoth.game_config.village_support''' &amp;amp;harr; ''integer''&lt;br /&gt;
* '''wesnoth.game_config.poison_amount''' &amp;amp;harr; ''integer''&lt;br /&gt;
* '''wesnoth.game_config.rest_heal_amount''' &amp;amp;harr; ''integer'&lt;br /&gt;
* '''wesnoth.game_config.recall_cost''' &amp;amp;harr; ''integer''&lt;br /&gt;
* '''wesnoth.game_config.combat_experience''' &amp;amp;harr; ''integer''&lt;br /&gt;
* '''wesnoth.game_config.kill_experience''' &amp;amp;harr; ''integer''&lt;br /&gt;
&lt;br /&gt;
Values of various game settings.&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.game_config.global_traits'''[''trait id''] &amp;amp;rarr;&lt;br /&gt;
&lt;br /&gt;
A table with named fields (trait id strings) holding the wml tables defining the traits. This contains all global traits the engine knows about, but race-specific traits are not included. The known fields and subtags of each element are the ones which were given in the wml definition of the [[SingleUnitWML|trait]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wesnoth.game_config.global_traits.strong.male_name)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.game_config.do_healing''' &amp;amp;harr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Whether healing will occur at the beginning of each side's turn.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.game_config.theme''' &amp;amp;harr; ''theme id''&lt;br /&gt;
&lt;br /&gt;
The currently active in-game theme.&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.game_config.debug''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Whether debug mode is currently active. Debug mode is activated by the --debug command-line parameter or the :debug in-game command.&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.game_config.debug_lua''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Whether Lua debug is enabled. Lua debug is activated by the --debug-lua command-line parameter. This does not seem to do anything by default.&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.game_config.mp_debug''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Whether MP debug is enabled. MP debug is activated in the same way as debug mode, but is only active in multiplayer games.&lt;br /&gt;
&lt;br /&gt;
* '''wesnoth.game_config.strict_lua''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Whether strict Lua mode is enabled. Strict Lua mode is activated by the --strict-lua command-line parameter and causes all deprecated Lua APIs to be completely removed from the engine.&lt;br /&gt;
&lt;br /&gt;
* {{DevFeature1.19|4}} '''wesnoth.game_config.palettes'''.''palette'' &amp;amp;rarr; ''list of colors''&lt;br /&gt;
&lt;br /&gt;
Returns the color palette with the given name, as defined by a '''[color_palette]''' tag in the [[GameConfigWML#Color_Palettes|game config]].&lt;br /&gt;
&lt;br /&gt;
* {{DevFeature1.19|4}} '''wesnoth.game_config.red_green_scale''' &amp;amp;rarr; ''list of colors''&lt;br /&gt;
&lt;br /&gt;
Returns the gradient used for health bars.&lt;br /&gt;
&lt;br /&gt;
* {{DevFeature1.19|4}} '''wesnoth.game_config.red_green_scale_text''' &amp;amp;rarr; ''list of colors''&lt;br /&gt;
&lt;br /&gt;
Returns the gradient used for health numbers.&lt;br /&gt;
&lt;br /&gt;
* {{DevFeature1.19|4}} '''wesnoth.game_config.blue_white_scale''' &amp;amp;rarr; ''list of colors''&lt;br /&gt;
&lt;br /&gt;
Returns the gradient used for experience bars.&lt;br /&gt;
&lt;br /&gt;
* {{DevFeature1.19|4}} '''wesnoth.game_config.blue_white_scale_text''' &amp;amp;rarr; ''list of colors''&lt;br /&gt;
&lt;br /&gt;
Returns the gradient used for experience numbers.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.races ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.races'''.''id'' &amp;amp;rarr; ''race info''&lt;br /&gt;
&lt;br /&gt;
Access defined [[UnitsWML#.5Brace.5D|races]]. Returns a [[LuaAPI/types#Race|race userdata]].&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.scenario ===&lt;br /&gt;
&lt;br /&gt;
Contains information about the current scenario&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.turns''' &amp;amp;harr; ''turn limit''&lt;br /&gt;
&lt;br /&gt;
The current turn limit of the scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.next''' &amp;amp;harr; ''scenario id''&lt;br /&gt;
&lt;br /&gt;
The ID of the scenario to transition to when this scenario ends.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.id''' &amp;amp;rarr; ''scenario id''&lt;br /&gt;
&lt;br /&gt;
The ID of the current scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.name''' &amp;amp;rarr; &lt;br /&gt;
&lt;br /&gt;
The name of the current scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.defeat_music''' &amp;amp;harr; ''list of music tracks''&lt;br /&gt;
&lt;br /&gt;
The music to play if you lose this scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.victory_music''' &amp;amp;harr; ''list of music tracks''&lt;br /&gt;
&lt;br /&gt;
The music to play if you win this scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.show_credits''' &amp;amp;harr; ''boolean''&lt;br /&gt;
&lt;br /&gt;
Whether credits should be shown when this scenario ends. Only relevant if '''wesnoth.scenario.next''' is nil.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.end_text''' &amp;amp;harr; ''text''&lt;br /&gt;
&lt;br /&gt;
The end text to show when the scenario ends. Only relevant if '''wesnoth.scenario.next''' is nil.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.end_text_duration''' &amp;amp;harr; ''duration''&lt;br /&gt;
&lt;br /&gt;
How long to show the end text for when the scenario ends. Only relevant if '''wesnoth.scenario.next''' is nil.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.difficulty''' &amp;amp;rarr; ''difficult''&lt;br /&gt;
&lt;br /&gt;
The difficulty level this scenario is being played on.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.type''' &amp;amp;rarr; ''tag name''&lt;br /&gt;
&lt;br /&gt;
The type of this scenario. One of the strings '''scenario''', '''multiplayer''', or '''test'''.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.era''' &amp;amp;rarr; ''era tag''&lt;br /&gt;
&lt;br /&gt;
The [era] tag active in this scenario. Accessing this will throw an error in single-player games.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.campaign''' &amp;amp;rarr; ''campaign tag''&lt;br /&gt;
&lt;br /&gt;
The [campaign] tag active in this scenario. Accessing this will throw an error in multiplayer or test games, so be sure to check '''wesnoth.scenario.type''' first in generic code.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.resources''' &amp;amp;rarr; ''list of resource tags''&lt;br /&gt;
&lt;br /&gt;
A list of [resource] tags active in this scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.modifications''' &amp;amp;rarr; ''list of modification tags''&lt;br /&gt;
&lt;br /&gt;
A list of [modification] tags active in this scenario.&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.scenario.mp_settings''' &amp;amp;rarr; ''table''&lt;br /&gt;
&lt;br /&gt;
In a multiplayer game, this is a proxy table which gives read only access to all MP-only configuration options which appear as attributes of [multiplayer] tag in a save game file. This allows accessing basically everything that can be set in the create game screen. The following keys exist in the returned table:&lt;br /&gt;
&lt;br /&gt;
* '''active_mods''' - A list of all active modification IDs&lt;br /&gt;
* '''hash''' - A hash of mp data&lt;br /&gt;
* '''mp_campaign''' - Name of mp campaign&lt;br /&gt;
* '''mp_scenario''' - ID of this mp scenario&lt;br /&gt;
* '''mp_scenario_name''' - Name of this mp scenario&lt;br /&gt;
* '''scenario''' - MP lobby title &lt;br /&gt;
* '''difficulty_define''' - The campaign difficulty string for an mp campaign&lt;br /&gt;
* '''mp_village_gold'''&lt;br /&gt;
* '''mp_village_support'''&lt;br /&gt;
* '''mp_num_turns'''&lt;br /&gt;
* '''mp_era''' - The id of the chosen era&lt;br /&gt;
* '''mp_eras''' - A list of all era ids&lt;br /&gt;
* '''mp_fog'''&lt;br /&gt;
* '''mp_shroud'''&lt;br /&gt;
* '''mp_random_start_time'''&lt;br /&gt;
* '''experience_modifier'''&lt;br /&gt;
* '''mp_use_map_settings'''&lt;br /&gt;
* '''mp_countdown''' - Whether the timer is enabled&lt;br /&gt;
* '''mp_countdown_action_bonus'''&lt;br /&gt;
* '''mp_countdown_init_time''' &lt;br /&gt;
* '''mp_countdown_reservoir_time'''&lt;br /&gt;
* '''mp_countdown_turn_bonus'''&lt;br /&gt;
* '''observer'''&lt;br /&gt;
* '''shuffle_sides'''&lt;br /&gt;
* '''savegame''' - Whether this is a reloaded game&lt;br /&gt;
* '''side_users''' - List of how sides are assigned to users (at game start)&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.terrain_types ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|12}}&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.terrain_types'''[''code''] &amp;amp;rarr; ''terrain info''&lt;br /&gt;
&lt;br /&gt;
Access defined [[TerrainWML|terrain types]] by their terrain code. Returns a table with the following keys:&lt;br /&gt;
&lt;br /&gt;
* '''id'''&lt;br /&gt;
* '''name'''&lt;br /&gt;
* '''editor_name'''&lt;br /&gt;
* '''description'''&lt;br /&gt;
* '''icon'''&lt;br /&gt;
* '''editor_image'''&lt;br /&gt;
* '''light'''&lt;br /&gt;
* '''village'''&lt;br /&gt;
* '''castle'''&lt;br /&gt;
* '''keep'''&lt;br /&gt;
* '''healing'''&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.unit_types ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.unit_types'''[''id''] &amp;amp;rarr; ''unit type info''&lt;br /&gt;
&lt;br /&gt;
Access defined [[UnitTypeWML|unit types]] by their ID. Returns a [[LuaAPI/types#Unit_Type|unit type userdata]].&lt;br /&gt;
&lt;br /&gt;
== Submodules ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;wesnoth&amp;lt;/tt&amp;gt; module also contains a number of submodules for working with particular aspects of the game.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.audio ===&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/audio|submodule]] containing functions for playing music and sound effects.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.achievements ===&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/achievements|submodule]] containing functions for working with in-game achievements.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.game_events ===&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/game_events|submodule]] containing functions for working with event handlers.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.map ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|11}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/map|submodule]] containing functions for querying and manipulating the game map.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|0}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/interface|submodule]] containing functions pertaining to the in-game UI.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.paths ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|0}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/paths|submodule]] containing functions related to pathfinding.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.schedule ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|14}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/schedule|submodule]] containing functions to manipulate the time of day schedule.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.sides ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|3}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/sides|submodule]] containing functions for manipulating the sides of a scenario.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.sync ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|14}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/sync|submodule]] containing functions to deal with multiplayer synchronization.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.units ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|0}}&lt;br /&gt;
&lt;br /&gt;
A [[LuaAPI/wesnoth/units|submodule]] containing functions to manipulate units on the map.&lt;br /&gt;
&lt;br /&gt;
[[Category: Lua Reference]]&lt;br /&gt;
&lt;br /&gt;
== Unsupported Functions ==&lt;br /&gt;
&lt;br /&gt;
The following functions exist in the '''wesnoth''' module but are not intended to be used:&lt;br /&gt;
&lt;br /&gt;
* wesnoth.allow_undo&lt;br /&gt;
* wesnoth.cancel_action&lt;br /&gt;
* wesnoth.clear_menu_item&lt;br /&gt;
* wesnoth.set_menu_item&lt;br /&gt;
* wesnoth.kernel_type&lt;br /&gt;
* wesnoth.log_replay&lt;br /&gt;
* wesnoth.print&lt;br /&gt;
* wesnoth.redraw&lt;br /&gt;
* wesnoth.add_known_unit&lt;br /&gt;
* wesnoth.get_era&lt;br /&gt;
* wesnoth.get_resource&lt;br /&gt;
&lt;br /&gt;
Some of these have WML equivalents, so if you need the functionality you should call the WML action directly (via [[#wesnoth.wml_actions|wml_actions]] or [[LuaAPI/wml#wml.fire|wml.fire]]). Others are internal functionality used in core Lua scripts, which are not intended for general use. These functions ''may'' be removed or changed without warning or going through a deprecation cycle.&lt;br /&gt;
&lt;br /&gt;
Examination of the '''wesnoth''' module will also reveal two additional subtables - the '''package''' table, which is where packages loaded by [[#wesnoth.require|wesnoth.require]] persist (meaning you can force '''wesnoth.require''' to reload a file by nulling out its entry in this table), and the '''experimental''' module, which contains functions that are available for use but without warranty - they may change without warning or going through a deprecation cycle. Use of both of these tables is unsupported.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73952</id>
		<title>GUIWidgetInstanceWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73952"/>
		<updated>2024-11-06T14:03:24Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Label */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Widget instance ==&lt;br /&gt;
Inside a grid (which is inside all container widgets) a widget is&lt;br /&gt;
instantiated. With this instantiation some more variables of a widget can&lt;br /&gt;
be tuned. This page will describe what can be tuned.&lt;br /&gt;
&lt;br /&gt;
== Widget ==&lt;br /&gt;
All widgets placed in the cell have some values in common:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| This value is used for the engine to identify 'special' items. This means that for example a text_box can get the proper initial value. This value should be unique or empty. Those special values are documented at the window definition that uses them. NOTE items starting with an underscore are used for composed widgets and these should be unique per composed widget.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;default&amp;quot;&lt;br /&gt;
| The id of the widget definition to use. This way it's possible to select a specific version of the widget e.g. a title label when the label is used as title.&lt;br /&gt;
|-&lt;br /&gt;
| linked_group&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The linked group the control belongs to.&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Most widgets have some text associated with them, this field contain the value of that text. Some widgets use this value for other purposes, this is documented at the widget. E.g. an image uses the filename in this field.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget a while (the time it takes can differ per widget) a short help can show up.This defines the text of that message. This field may not be empty when 'help' is set.&lt;br /&gt;
|-&lt;br /&gt;
| help&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget and press F10 (or the key the user defined for the help tip) a help message can show up. This help message might be the same as the tooltip but in general (if used) this message should show more help. This defines the text of that message.&lt;br /&gt;
|-&lt;br /&gt;
| use_tooltip_on_label_overflow&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If the text on the label is truncated and the tooltip is empty the label can be used for the tooltip. If this variable is set to true this will happen.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_mode&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The mode for showing the debug border. This border shows the area reserved for a widget. This function is only meant for debugging and might not be available in all Wesnoth binaries. Available modes: &lt;br /&gt;
* '''0:''' no border. &lt;br /&gt;
* '''1:''' 1 pixel border. &lt;br /&gt;
* '''2:''' floodfill the widget area.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the debug border.&lt;br /&gt;
|-&lt;br /&gt;
| size_text&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Sets the minimum width of the widget depending on the text in it. (Note not implemented yet.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Button ==&lt;br /&gt;
A button is a control that can be pushed to start an action or close a dialog.&lt;br /&gt;
&lt;br /&gt;
Instance of a button. When a button has a return value it sets the&lt;br /&gt;
return value for the window. Normally this closes the window and returns&lt;br /&gt;
this value to the caller. The return value can either be defined by the&lt;br /&gt;
user or determined from the id of the button. The return value has a&lt;br /&gt;
higher precedence as the one defined by the id. (Of course it's weird to&lt;br /&gt;
give a button an id and then override its return value.)&lt;br /&gt;
&lt;br /&gt;
When the button doesn't have a standard id, but you still want to use the&lt;br /&gt;
return value of that id, use return_value_id instead. This has a higher&lt;br /&gt;
precedence as return_value.&lt;br /&gt;
&lt;br /&gt;
List with the button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Supported values for return_value_id:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!string&lt;br /&gt;
!value&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;ok&amp;quot;||-1||Equivalent to closing the dialog by pressing the Enter key&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;cancel&amp;quot;||-2||Equivalent to closing the dialog by pressing the Esc key&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;quit&amp;quot;||-2||An alias for cancel&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;&amp;quot;||N/A||Clears any previously set return_value_id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Combobox ==&lt;br /&gt;
[[File:Combobox.png|frame|right|A Combobox with its list open]]&lt;br /&gt;
A widget with a text box and a dropdown list. Selecting an element from the list sets the value of the text box to that item of the list. The user can also manually enter a value in the text box.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! key !! type !! default !! description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The text of the combobox&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;combobox&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Drawing ==&lt;br /&gt;
A drawing is widget with a fixed size and gives access to the canvas of the widget in the window instance. This allows special display only widgets.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is not zero the drawing functions as a&lt;br /&gt;
fixed size drawing.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| draw&lt;br /&gt;
| [[GUIVariable#config|config]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The config containing the drawing.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Grid Listbox ==&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Horizontal listbox ==&lt;br /&gt;
A horizontal listbox is a control that holds several items of the same type.  Normally the items in a listbox are ordered in rows, this version orders them in columns instead.&lt;br /&gt;
&lt;br /&gt;
List with the horizontal listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a horizontal listbox,&lt;br /&gt;
the widgets need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
An image shows a static image whose path is specified by its '''[[GUIWidgetInstanceWML#Widget|label]]''' key. Unlike other widgets, the '''label''' key here is not translatable since it specifies a path. The path is a standard WML path, i.e., &amp;lt;code&amp;gt;label=&amp;quot;units/konrad.png&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;label=&amp;quot;~add-ons/MyAddon/image/test.png&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It has no other extra fields.&lt;br /&gt;
&lt;br /&gt;
== Label ==&lt;br /&gt;
A label displays text provided via the '''[[GUIWidgetInstanceWML#Widget|label]]''' key that can be wrapped but no scrollbars are provided. For a version with scrollbars, see the [[GUIWidgetInstanceWML#Scroll_Label|Scroll Label]] widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Title Label.png|frame|right|A Label with definition &amp;quot;title&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
List with the label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| wrap || [[GUIVariable#bool|bool]] || false || Is wrapping enabled for the label.&lt;br /&gt;
|-&lt;br /&gt;
| characters_per_line || [[GUIVariable#unsigned|unsigned]] || 0 || Sets the maximum number of characters per line. The amount is an approximation since the width of a character differs. E.g. iii is smaller than MMM. When the value is non-zero it also implies '''wrap''' is true. &lt;br /&gt;
When having long strings, wrapping them can increase readability. A rule of thumb is 66 characters per line is considered the optimum for a one column text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| can_shrink || [[GUIVariable#bool|bool]] || false || Whether the label can shrink past its optimal size.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Listbox ==&lt;br /&gt;
A listbox is a control that holds several items of the same type. Normally the items in a listbox are ordered in rows, this version might allow more options for ordering the items in the future.&lt;br /&gt;
&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a listbox, the widgets&lt;br /&gt;
need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Matrix ==&lt;br /&gt;
List with the matrix specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Menu Button ==&lt;br /&gt;
[[File:Menu Button.png|thumb|left|A Menu Button with it's list open.]]&lt;br /&gt;
A button that shows a dropdown list when clicked. The user can select any one of the predefined options.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;menu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Minimap ==&lt;br /&gt;
A minimap to show the gamemap, this only shows the map and has no interaction options. This version is used for map previews, there will be a another version which allows interaction.&lt;br /&gt;
&lt;br /&gt;
A minimap has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Multiline Text ==&lt;br /&gt;
Base class for a multiline text area.  Not to be used directly in a GUI, use the [[GUIWidgetInstanceWML#Scroll_Text|scroll_text]] widget instead.&lt;br /&gt;
&lt;br /&gt;
The following variables exist:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multimenu Button ==&lt;br /&gt;
[[File:Multimenu Button.png|thumb|right|A Multimenu Button with its list open]]&lt;br /&gt;
A widget clicking on which shows a list from which one or more options can be selected.&lt;br /&gt;
&lt;br /&gt;
List with the multimenu_button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value || [[GUIVariable#int|int]] || 0 || The return value.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_shown || [[GUIVariable#int|int]] || -1 || The maximum number of currently selected values to list on the button.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;multimenu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| checkbox || [[GUIVariable#bool|bool]] || &amp;quot;&amp;quot; || Whether the checkbox alongside this option is selected or not.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multi page ==&lt;br /&gt;
A multi page is a control that contains several 'pages' of which only one is visible. The pages can contain the same widgets containing the same 'kind' of data or look completely different.&lt;br /&gt;
&lt;br /&gt;
List with the multi page specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| page_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a multi page item looks. It must contain the grid definition for at least one page.&lt;br /&gt;
|-&lt;br /&gt;
| page_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the multi page. Every row must have the same number of columns as the 'page_definition'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Panel ==&lt;br /&gt;
A panel is an item which can hold other items. The difference between a grid and a panel is that it's possible to define how a panel looks. A grid in an invisible container to just hold the items.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Password box ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the password box.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Progress bar ==&lt;br /&gt;
A progress bar shows the progress of a certain object.&lt;br /&gt;
&lt;br /&gt;
A progress bar has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Repeating button ==&lt;br /&gt;
A repeating_button is a control that can be pushed down and repeat a certain action. Once the button is down every x milliseconds it is down a new down event is triggered.&lt;br /&gt;
&lt;br /&gt;
== Rich Label ==&lt;br /&gt;
A label that shows formatted text marked up with [[Help markup]]. It can show embedded images, links and tables inside text.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#int|int]] || 500 || Width of its internal formatted content. Text will wrap beyond this width.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll label ==&lt;br /&gt;
A scroll label is a label that wraps its text and also has a vertical scrollbar. This way a text can't be too long to be shown for this widget.&lt;br /&gt;
&lt;br /&gt;
List with the scroll label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scrollbar panel ==&lt;br /&gt;
Instance of a scrollbar_panel.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar_panel specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a scrollbar_panel item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Spacer ==&lt;br /&gt;
A spacer is a dummy item to either fill in a widget since no empty items are allowed or to reserve a fixed space.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is non-zero the spacer functions as a&lt;br /&gt;
fixed size spacer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The width of the spacer.&lt;br /&gt;
|-&lt;br /&gt;
| height || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The height of the spacer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Tab Container ==&lt;br /&gt;
&lt;br /&gt;
A container widget that can show its contents separated into various pages, each of which are accessible.&lt;br /&gt;
&lt;br /&gt;
It can contain one or more &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tags inside it, each defining a tab's name, image (if any) and the contents of the tag, specified by the &amp;lt;code&amp;gt;[data]&amp;lt;/code&amp;gt; tag inside the &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
=== Subtag [tab] ===&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| name || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the tab&lt;br /&gt;
|-&lt;br /&gt;
| image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image for the tab to be shown alongside the name, if any&lt;br /&gt;
|-&lt;br /&gt;
| [data] || [[GUIVariable#grid|grid]] || empty grid || This subtag contains a grid that defines the contents for this tab.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text box ==&lt;br /&gt;
A single line text entry widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Text Box.png|frame|right|A Text Box]]&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| editable || [[GUIVariable#bool|bool]] || &amp;quot;true&amp;quot; || If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle panel ==&lt;br /&gt;
A toggle panel is an item which can hold other items. The difference between&lt;br /&gt;
a grid and a panel is that it's possible to define how a panel looks. A grid&lt;br /&gt;
in an invisible container to just hold the items. The toggle panel is a&lt;br /&gt;
combination of the panel and a toggle button, it allows a toggle button with&lt;br /&gt;
its own grid.&lt;br /&gt;
&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Tree view ==&lt;br /&gt;
A tree view is a control that holds several items of the same or different types. The items shown are called tree view nodes and when a node has children, these can be shown or hidden. Nodes that contain children need to provide a clickable button in order to fold or unfold the children.&lt;br /&gt;
&lt;br /&gt;
List with the tree view specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| indention_step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of pixels every level of nodes is indented from the previous level.&lt;br /&gt;
|-&lt;br /&gt;
| node&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The tree view can contain multiple node sections. This part needs more documentation.&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE more documentation and examples are needed.&lt;br /&gt;
&lt;br /&gt;
== Vertical scrollbar ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Viewport ==&lt;br /&gt;
A viewport is an special widget used to view only a part of the widget it `holds'.&lt;br /&gt;
&lt;br /&gt;
List with the viewport specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grow_direction&lt;br /&gt;
| [[GUIVariable#grow_direction|grow_direction]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The direction in which new items grow.&lt;br /&gt;
|-&lt;br /&gt;
| parallel_items&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The number of items that are growing in parallel.&lt;br /&gt;
|-&lt;br /&gt;
| item_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The definition of a new item.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll Text ==&lt;br /&gt;
A multiline text area that shows a scrollbar if the text gets too long.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar container specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of this scroll_text can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slider ==&lt;br /&gt;
&lt;br /&gt;
A slider is a control that can select a value by moving a grip on a groove.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| best_slider_length&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The best length for the sliding part.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The minimum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The maximum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of items the slider's value increases with one step.&lt;br /&gt;
|-&lt;br /&gt;
| value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The value of the slider.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the minimum value is chosen there might be the need for a special value (eg off). When this key has a value that value will be shown if the minimum is selected.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the maximum value is chosen there might be the need for a special value (eg unlimited)). When this key has a value that value will be shown if the maximum is selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle button ==&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73951</id>
		<title>LuaAPI/types/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73951"/>
		<updated>2024-11-05T16:24:27Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Widget methods */ - typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The '''widget''' userdata offers access to a widget of a GUI2 dialog. While there is only one type of widget userdata that covers all widgets including the window itself, the properties of a widget userdata are different for each type of widget. Indexing a widget's userdata can either be used to access a child widget or to set or get a property of a widget. Some properties are read-only or write-only; the properties depend on the type of the widget.&lt;br /&gt;
&lt;br /&gt;
An example of accessing a child widget:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function preshow(dialog)&lt;br /&gt;
  local okay_button = dialog.okay_button&lt;br /&gt;
  -- okay_button is now a handle to the the widget's child with the id 'okay_button' &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widget Attributes ==&lt;br /&gt;
&lt;br /&gt;
=== selected ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected''' &amp;amp;harr; ''boolean''&lt;br /&gt;
* Available on: '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
Whether the item is selected or not. Note that this should only be used for widgets that have only 2 states. In particular, there exist 3-State toggle_buttons (for example in listbox headers). For those, selected_index must be used instead.&lt;br /&gt;
&lt;br /&gt;
=== selected_index ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_index''' &amp;amp;harr; ''index''&lt;br /&gt;
* Available on: '''[listbox]''', '''[multi_page]''', '''[stacked_widget]''', '''[menu_button]''', '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
The selected index of the item. For '''[toggle_button]''' and '''[toggle_panel]''', this is the same as '''selected''' only encoded as a number (1 for false or 2 for true) instead of a boolean.&lt;br /&gt;
&lt;br /&gt;
For a  '''[listbox]'''with '''has_maximum=false''' and more than one item selected, reading '''selected_index''' will return the first selected index.&lt;br /&gt;
&lt;br /&gt;
For a '''[stacked_widget]''', only the layer specified by '''selected_index''' will be displayed and receive events (callbacks will only be triggered on the selected layer).&lt;br /&gt;
A '''selected_index''' of 0 represents all layers being selected, with events only being received by the layer with the highest index.  Note that term ''selected'' for the ''layer'' of a stacked_widget is not the same as the '''selected''' ''widget'' attribute.&lt;br /&gt;
&lt;br /&gt;
=== text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''text''' &amp;amp;harr; ''text''&lt;br /&gt;
* Available on: '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
The text of the textbox.&lt;br /&gt;
&lt;br /&gt;
=== value ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''value''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[slider]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the slider.&lt;br /&gt;
&lt;br /&gt;
=== percentage ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''percentage''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[progress_bar]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the progress bar, between 0 and 100.&lt;br /&gt;
&lt;br /&gt;
=== selected_item_path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_item_path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view]'''&lt;br /&gt;
&lt;br /&gt;
A table describing the currently selected node. If for example, in the following treeview, Item 9 is selected, the result will be {2,1,3}.&lt;br /&gt;
&lt;br /&gt;
 +Section1&lt;br /&gt;
  +Subsection11&lt;br /&gt;
   *Item1&lt;br /&gt;
   *Item2&lt;br /&gt;
   *Item3&lt;br /&gt;
  +Subsection12&lt;br /&gt;
   *Item4&lt;br /&gt;
   *Item5&lt;br /&gt;
   *Item6&lt;br /&gt;
 +Section2&lt;br /&gt;
  +Subsection21&lt;br /&gt;
   *Item7&lt;br /&gt;
   *Item8&lt;br /&gt;
   *Item9&lt;br /&gt;
  +Subsection22&lt;br /&gt;
   *Item10&lt;br /&gt;
   *Item11&lt;br /&gt;
   *Item12&lt;br /&gt;
&lt;br /&gt;
=== path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
A table describing this node in the overall treeview. See [[#selected_item_path|selected_item_path]] for the meaning of the table..&lt;br /&gt;
&lt;br /&gt;
=== unfolded ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unfolded''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
Control whether a tree node is currently expanded or not.&lt;br /&gt;
&lt;br /&gt;
=== unit ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unit''' &amp;amp;larr; ''unit or unit type''&lt;br /&gt;
* Available on: '''[unit_preview_pane]'''&lt;br /&gt;
&lt;br /&gt;
Change the displayed unit or unit type in the preview pane.&lt;br /&gt;
&lt;br /&gt;
=== item_count ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''item_count''' &amp;amp;rarr; ''number of items''&lt;br /&gt;
* Available on: '''[multi_page]''', '''[listbox]'''&lt;br /&gt;
&lt;br /&gt;
The number of items in the container widget.&lt;br /&gt;
&lt;br /&gt;
=== use_markup ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''use_markup''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Sets whether the widget's label will parse [[Pango formatting]].&lt;br /&gt;
&lt;br /&gt;
=== label ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''label''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]''', '''[image]'''&lt;br /&gt;
&lt;br /&gt;
The widget's label. Technically this is a special string used in the widget's wml definition. It usually does what one would expect, but also sets the image for '''image''' widgets.  For '''[text_box]''', use '''text''' for initial values.&lt;br /&gt;
&lt;br /&gt;
=== marked_up_text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''marked_up_text''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Shortcut for setting label and use_markup=yes.&lt;br /&gt;
&lt;br /&gt;
=== enabled ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''enabled''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
=== tooltip ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''tooltip''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
=== visible ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''visible''' &amp;amp;larr; ''visibility string''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
Determines whether the widget is visible onscreen. The following visibility statuses are recognized:&lt;br /&gt;
{| clasS=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! String value !! Boolean shorthand !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| visible || true || The widget is visible and handles events.&lt;br /&gt;
|-&lt;br /&gt;
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.&lt;br /&gt;
|-&lt;br /&gt;
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''type''' &amp;amp;rarr; ''string''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Returns a string specifying the type of the widget.&lt;br /&gt;
&lt;br /&gt;
== Widget callbacks ==&lt;br /&gt;
&lt;br /&gt;
=== on_modified ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_modified''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: Most widgets, in particular '''[slider]''', '''[toggle_button]''', '''[listbox]''', '''[menu_button]''', '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user changes the value of the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_left_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_left_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_button_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_button_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: '''[button]''', '''[repeating_button]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the button. This can differ from '''on_left_click''', depending on the type of widget. For example, on a '''[repeating_button]''' it will fire multiple times if the user holds the mouse button down.&lt;br /&gt;
&lt;br /&gt;
== Widget methods ==&lt;br /&gt;
&lt;br /&gt;
Any function defined in the [[LuaAPI/gui/widget|gui.widget]] module and taking a widget as its first parameter can be called as a method of a widget. This includes any functions that are added to the module by user code. Note that these methods are available even if the widget itself doesn't support that function, so in some cases it may be necessary to check '''widget.type''' before calling the method.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73950</id>
		<title>LuaAPI/types/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73950"/>
		<updated>2024-11-05T14:13:18Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* selected_index */ - clarify stacked_widget&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The '''widget''' userdata offers access to a widget of a GUI2 dialog. While there is only one type of widget userdata that covers all widgets including the window itself, the properties of a widget userdata are different for each type of widget. Indexing a widget's userdata can either be used to access a child widget or to set or get a property of a widget. Some properties are read-only or write-only; the properties depend on the type of the widget.&lt;br /&gt;
&lt;br /&gt;
An example of accessing a child widget:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function preshow(dialog)&lt;br /&gt;
  local okay_button = dialog.okay_button&lt;br /&gt;
  -- okay_button is now a handle to the the widget's child with the id 'okay_button' &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widget Attributes ==&lt;br /&gt;
&lt;br /&gt;
=== selected ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected''' &amp;amp;harr; ''boolean''&lt;br /&gt;
* Available on: '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
Whether the item is selected or not. Note that this should only be used for widgets that have only 2 states. In particular, there exist 3-State toggle_buttons (for example in listbox headers). For those, selected_index must be used instead.&lt;br /&gt;
&lt;br /&gt;
=== selected_index ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_index''' &amp;amp;harr; ''index''&lt;br /&gt;
* Available on: '''[listbox]''', '''[multi_page]''', '''[stacked_widget]''', '''[menu_button]''', '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
The selected index of the item. For '''[toggle_button]''' and '''[toggle_panel]''', this is the same as '''selected''' only encoded as a number (1 for false or 2 for true) instead of a boolean.&lt;br /&gt;
&lt;br /&gt;
For a  '''[listbox]'''with '''has_maximum=false''' and more than one item selected, reading '''selected_index''' will return the first selected index.&lt;br /&gt;
&lt;br /&gt;
For a '''[stacked_widget]''', only the layer specified by '''selected_index''' will be displayed and receive events (callbacks will only be triggered on the selected layer).&lt;br /&gt;
A '''selected_index''' of 0 represents all layers being selected, with events only being received by the layer with the highest index.  Note that term ''selected'' for the ''layer'' of a stacked_widget is not the same as the '''selected''' ''widget'' attribute.&lt;br /&gt;
&lt;br /&gt;
=== text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''text''' &amp;amp;harr; ''text''&lt;br /&gt;
* Available on: '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
The text of the textbox.&lt;br /&gt;
&lt;br /&gt;
=== value ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''value''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[slider]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the slider.&lt;br /&gt;
&lt;br /&gt;
=== percentage ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''percentage''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[progress_bar]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the progress bar, between 0 and 100.&lt;br /&gt;
&lt;br /&gt;
=== selected_item_path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_item_path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view]'''&lt;br /&gt;
&lt;br /&gt;
A table describing the currently selected node. If for example, in the following treeview, Item 9 is selected, the result will be {2,1,3}.&lt;br /&gt;
&lt;br /&gt;
 +Section1&lt;br /&gt;
  +Subsection11&lt;br /&gt;
   *Item1&lt;br /&gt;
   *Item2&lt;br /&gt;
   *Item3&lt;br /&gt;
  +Subsection12&lt;br /&gt;
   *Item4&lt;br /&gt;
   *Item5&lt;br /&gt;
   *Item6&lt;br /&gt;
 +Section2&lt;br /&gt;
  +Subsection21&lt;br /&gt;
   *Item7&lt;br /&gt;
   *Item8&lt;br /&gt;
   *Item9&lt;br /&gt;
  +Subsection22&lt;br /&gt;
   *Item10&lt;br /&gt;
   *Item11&lt;br /&gt;
   *Item12&lt;br /&gt;
&lt;br /&gt;
=== path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
A table describing this node in the overall treeview. See [[#selected_item_path|selected_item_path]] for the meaning of the table..&lt;br /&gt;
&lt;br /&gt;
=== unfolded ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unfolded''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
Control whether a tree node is currently expanded or not.&lt;br /&gt;
&lt;br /&gt;
=== unit ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unit''' &amp;amp;larr; ''unit or unit type''&lt;br /&gt;
* Available on: '''[unit_preview_pane]'''&lt;br /&gt;
&lt;br /&gt;
Change the displayed unit or unit type in the preview pane.&lt;br /&gt;
&lt;br /&gt;
=== item_count ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''item_count''' &amp;amp;rarr; ''number of items''&lt;br /&gt;
* Available on: '''[multi_page]''', '''[listbox]'''&lt;br /&gt;
&lt;br /&gt;
The number of items in the container widget.&lt;br /&gt;
&lt;br /&gt;
=== use_markup ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''use_markup''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Sets whether the widget's label will parse [[Pango formatting]].&lt;br /&gt;
&lt;br /&gt;
=== label ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''label''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]''', '''[image]'''&lt;br /&gt;
&lt;br /&gt;
The widget's label. Technically this is a special string used in the widget's wml definition. It usually does what one would expect, but also sets the image for '''image''' widgets.  For '''[text_box]''', use '''text''' for initial values.&lt;br /&gt;
&lt;br /&gt;
=== marked_up_text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''marked_up_text''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Shortcut for setting label and use_markup=yes.&lt;br /&gt;
&lt;br /&gt;
=== enabled ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''enabled''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
=== tooltip ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''tooltip''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
=== visible ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''visible''' &amp;amp;larr; ''visibility string''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
Determines whether the widget is visible onscreen. The following visibility statuses are recognized:&lt;br /&gt;
{| clasS=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! String value !! Boolean shorthand !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| visible || true || The widget is visible and handles events.&lt;br /&gt;
|-&lt;br /&gt;
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.&lt;br /&gt;
|-&lt;br /&gt;
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''type''' &amp;amp;rarr; ''string''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Returns a string specifying the type of the widget.&lt;br /&gt;
&lt;br /&gt;
== Widget callbacks ==&lt;br /&gt;
&lt;br /&gt;
=== on_modified ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_modified''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: Most widgets, in particular '''[slider]''', '''[toggle_button]''', '''[listbox]''', '''[menu_button]''', '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user changes the value of the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_left_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_left_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_button_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_button_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: '''[button]''', '''[repeating_button]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the button. This can differ from '''on_left_click''', depending on the type of widget. For example, on a '''[repeating_button]''' it will fire multiple times if the user holds the mouse button down.&lt;br /&gt;
&lt;br /&gt;
== Widget methods ==&lt;br /&gt;
&lt;br /&gt;
Any function defined in the [[LuaAPI/gui/widget|gui.widget]] module and taking a widget as its first parameter can be called as a method of a widget. This includes any functions that are added to the module by user code. Note that these methods are available even if the widget itself doesn't support that function, so in some cases it may be necessary to check '''widget.type''' befor calling the method.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73949</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73949"/>
		<updated>2024-11-05T06:04:28Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Text */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.  Deprecated, replaced by mirror.&lt;br /&gt;
|-&lt;br /&gt;
| mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73948</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73948"/>
		<updated>2024-11-05T06:03:56Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Text */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.  Deprecated, replaced by mirror.&lt;br /&gt;
|-&lt;br /&gt;
| mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73947</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73947"/>
		<updated>2024-11-05T05:54:49Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Image */  - vertical_mirror depr&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.  Deprecated, replaced by mirror.&lt;br /&gt;
|-&lt;br /&gt;
| mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73946</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73946"/>
		<updated>2024-11-05T05:49:16Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Rounded Rectangle */ - color &amp;gt; f_color&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73945</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73945"/>
		<updated>2024-11-05T05:46:04Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Rectangle */  - color -&amp;gt; f_color&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73944</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73944"/>
		<updated>2024-11-05T05:44:39Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Line */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Talk:GUIVariable&amp;diff=73943</id>
		<title>Talk:GUIVariable</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Talk:GUIVariable&amp;diff=73943"/>
		<updated>2024-11-05T05:40:42Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;resize_mode lists three values - perhaps they are the only ones actually used?&lt;br /&gt;
																									&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
    enum class resize_mode {&lt;br /&gt;
        scale,&lt;br /&gt;
        scale_sharp,&lt;br /&gt;
        stretch,&lt;br /&gt;
        tile,&lt;br /&gt;
        tile_center,&lt;br /&gt;
        tile_highres,&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
grow_direction looks like it was just copied from resize_mode.  Would that be this?&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct grow_direction_defines&lt;br /&gt;
{&lt;br /&gt;
    static constexpr const char* const horizontal = &amp;quot;horizontal&amp;quot;;&lt;br /&gt;
    static constexpr const char* const vertical = &amp;quot;vertical&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    ENUM_AND_ARRAY(horizontal, vertical)&lt;br /&gt;
};&lt;br /&gt;
using grow_direction = string_enums::enum_base&amp;lt;grow_direction_defines&amp;gt;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[User:White haired uncle|White haired uncle]] ([[User talk:White haired uncle|talk]]) 05:36, 5 November 2024 (UTC)&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73942</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73942"/>
		<updated>2024-11-05T05:38:36Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Circle */  - color &amp;gt; f_color&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Talk:GUIVariable&amp;diff=73941</id>
		<title>Talk:GUIVariable</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Talk:GUIVariable&amp;diff=73941"/>
		<updated>2024-11-05T05:36:39Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: Created page with &amp;quot;resize_mode lists three values - perhaps they are the only ones actually used? 																									 &amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;     enum class resize_mode {         scal...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;resize_mode lists three values - perhaps they are the only ones actually used?&lt;br /&gt;
																									&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
    enum class resize_mode {&lt;br /&gt;
        scale,&lt;br /&gt;
        scale_sharp,&lt;br /&gt;
        stretch,&lt;br /&gt;
        tile,&lt;br /&gt;
        tile_center,&lt;br /&gt;
        tile_highres,&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
grow_direction looks like it was just copied from resize_mode.  Would that be this?&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct grow_direction_defines&lt;br /&gt;
{&lt;br /&gt;
    static constexpr const char* const horizontal = &amp;quot;horizontal&amp;quot;;&lt;br /&gt;
    static constexpr const char* const vertical = &amp;quot;vertical&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    ENUM_AND_ARRAY(horizontal, vertical)&lt;br /&gt;
};&lt;br /&gt;
using grow_direction = string_enums::enum_base&amp;lt;grow_direction_defines&amp;gt;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both of the above speak of acting on an image, which I guess is kind of true but perhaps there's a better word to avoid confusion with [image].&lt;br /&gt;
[[User:White haired uncle|White haired uncle]] ([[User talk:White haired uncle|talk]]) 05:36, 5 November 2024 (UTC)&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73940</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73940"/>
		<updated>2024-11-05T03:16:42Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Circle */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 1&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's white.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIVariable&amp;diff=73939</id>
		<title>GUIVariable</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIVariable&amp;diff=73939"/>
		<updated>2024-11-05T03:14:06Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Simple types */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Variables ==&lt;br /&gt;
In various parts of the GUI there are several variables types in use. This&lt;br /&gt;
page describes them.&lt;br /&gt;
&lt;br /&gt;
== Simple types ==&lt;br /&gt;
The simple types are types which have one value or a short list of options.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Variable !!Description&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;unsigned&amp;quot;&amp;gt;unsigned&amp;lt;/span&amp;gt;&lt;br /&gt;
| Unsigned number (positive whole numbers and zero).&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_unsigned&amp;quot;&amp;gt;f_unsigned&amp;lt;/span&amp;gt;&lt;br /&gt;
| Unsigned number or formula returning an unsigned number.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;int&amp;quot;&amp;gt;int&amp;lt;/span&amp;gt;&lt;br /&gt;
| Signed number (whole numbers).&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_int&amp;quot;&amp;gt;f_int&amp;lt;/span&amp;gt;&lt;br /&gt;
| Signed number or formula returning an signed number.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;bool&amp;quot;&amp;gt;bool&amp;lt;/span&amp;gt;&lt;br /&gt;
| A boolean value accepts the normal values as the rest of the game.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_bool&amp;quot;&amp;gt;f_bool&amp;lt;/span&amp;gt;&lt;br /&gt;
| Boolean value or a formula returning a boolean value.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;string&amp;quot;&amp;gt;string&amp;lt;/span&amp;gt;&lt;br /&gt;
| A text.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;tstring&amp;quot;&amp;gt;tstring&amp;lt;/span&amp;gt;&lt;br /&gt;
| A translatable string.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_tstring&amp;quot;&amp;gt;f_tstring&amp;lt;/span&amp;gt;&lt;br /&gt;
| Formula returning a translatable string.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;function&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt;&lt;br /&gt;
| A string containing a set of function definition for the formula language.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;color&amp;quot;&amp;gt;color&amp;lt;/span&amp;gt;&lt;br /&gt;
| A string which contains the color, this a group of 4 numbers between 0 and 255 separated by commas. The numbers are red component, green component, blue component and alpha.  An alpha of 0 is fully transparent, while an alpha of 255 is fully opaque.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_color&amp;quot;&amp;gt;f_color&amp;lt;/span&amp;gt;&lt;br /&gt;
|  A color, or a formula returning a color value.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;font_style&amp;quot;&amp;gt;font_style&amp;lt;/span&amp;gt;&lt;br /&gt;
| A string which contains the style of the font: &lt;br /&gt;
* normal    normal font &lt;br /&gt;
* bold      bold font &lt;br /&gt;
* italic    italic font &lt;br /&gt;
* underline underlined font &lt;br /&gt;
Since SDL has problems combining these styles only one can be picked. Once SDL will allow multiple options, this type will be transformed to a comma separated list. If empty we default to the normal style. Since the render engine is replaced by Pango markup this field will change later on. Note widgets that allow marked up text can use markup to change the font style.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;v_align&amp;quot;&amp;gt;v_align&amp;lt;/span&amp;gt;&lt;br /&gt;
| Vertical alignment; how an item is aligned vertically in the available space. Possible values: &lt;br /&gt;
* top    aligned at the top &lt;br /&gt;
* bottom aligned at the bottom &lt;br /&gt;
* center centered &lt;br /&gt;
When nothing is set or an another value as in the list the item is centered.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;h_align&amp;quot;&amp;gt;h_align&amp;lt;/span&amp;gt;&lt;br /&gt;
| Horizontal alignment; how an item is aligned horizontally in the available space. Possible values: &lt;br /&gt;
* left   aligned at the left side &lt;br /&gt;
* right  aligned at the right side &lt;br /&gt;
* center centered&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_h_align&amp;quot;&amp;gt;f_h_align&amp;lt;/span&amp;gt;&lt;br /&gt;
| A horizontal alignment or a formula returning a horizontal alignment.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;border&amp;quot;&amp;gt;border&amp;lt;/span&amp;gt;&lt;br /&gt;
| Comma separated list of borders to use. Possible values: &lt;br /&gt;
* left   border at the left side &lt;br /&gt;
* right  border at the right side &lt;br /&gt;
* top    border at the top &lt;br /&gt;
* bottom border at the bottom &lt;br /&gt;
* all    alias for &amp;quot;left, right, top, bottom&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;scrollbar_mode&amp;quot;&amp;gt;scrollbar_mode&amp;lt;/span&amp;gt;&lt;br /&gt;
| How to show the scrollbar of a widget. Possible values: &lt;br /&gt;
* always       The scrollbar is always shown, regardless whether it's required or not. &lt;br /&gt;
* never        The scrollbar is never shown, even not when needed. (Note when setting this mode dialogs might not properly fit anymore). &lt;br /&gt;
* auto         Shows the scrollbar when needed. The widget will reserve space for the scrollbar, but only show when needed. &lt;br /&gt;
* initial_auto Like auto, but when the scrollbar is not needed the space is not reserved. &lt;br /&gt;
Use auto when the list can be changed dynamically eg the game list in the lobby. For optimization you can also use auto when you really expect a scrollbar, but don't want it to be shown when not needed eg the language list will need a scrollbar on most screens.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;resize_mode&amp;quot;&amp;gt;resize_mode&amp;lt;/span&amp;gt;&lt;br /&gt;
| Determines how an image is resized. Possible values: &lt;br /&gt;
* scale        The image is scaled. &lt;br /&gt;
* stretch      The first row or column of pixels is copied over the entire image. (Can only be used to scale resize in one direction, else falls back to scale.) &lt;br /&gt;
* tile         The image is placed several times until the entire surface is filled. The last images are truncated.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;grow_direction&amp;quot;&amp;gt;grow_direction&amp;lt;/span&amp;gt;&lt;br /&gt;
| Determines how an image is resized. Possible values: &lt;br /&gt;
* scale        The image is scaled. &lt;br /&gt;
* stretch      The first row or column of pixels is copied over the entire image. (Can only be used to scale resize in one direction, else falls back to scale.) &lt;br /&gt;
* tile         The image is placed several times until the entire surface is filled. The last images are truncated.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Section types ==&lt;br /&gt;
For more complex parts, there are sections. Sections contain of several&lt;br /&gt;
lines of WML and can have sub sections. For example a grid has sub sections&lt;br /&gt;
which contain various widgets. Here's the list of sections.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span id=&amp;quot;section&amp;quot;&amp;gt;section&amp;lt;/span&amp;gt;&lt;br /&gt;
| A generic section. The documentation about the section should describe the section in further detail.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span id=&amp;quot;grid&amp;quot;&amp;gt;grid&amp;lt;/span&amp;gt;&lt;br /&gt;
| A grid contains several widgets. (TODO add link to generic grid page.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIVariable&amp;diff=73938</id>
		<title>GUIVariable</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIVariable&amp;diff=73938"/>
		<updated>2024-11-05T03:06:55Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Simple types */  - add f_color, fix color description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Variables ==&lt;br /&gt;
In various parts of the GUI there are several variables types in use. This&lt;br /&gt;
page describes them.&lt;br /&gt;
&lt;br /&gt;
== Simple types ==&lt;br /&gt;
The simple types are types which have one value or a short list of options.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Variable !!Description&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;unsigned&amp;quot;&amp;gt;unsigned&amp;lt;/span&amp;gt;&lt;br /&gt;
| Unsigned number (positive whole numbers and zero).&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_unsigned&amp;quot;&amp;gt;f_unsigned&amp;lt;/span&amp;gt;&lt;br /&gt;
| Unsigned number or formula returning an unsigned number.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;int&amp;quot;&amp;gt;int&amp;lt;/span&amp;gt;&lt;br /&gt;
| Signed number (whole numbers).&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_int&amp;quot;&amp;gt;f_int&amp;lt;/span&amp;gt;&lt;br /&gt;
| Signed number or formula returning an signed number.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;bool&amp;quot;&amp;gt;bool&amp;lt;/span&amp;gt;&lt;br /&gt;
| A boolean value accepts the normal values as the rest of the game.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_bool&amp;quot;&amp;gt;f_bool&amp;lt;/span&amp;gt;&lt;br /&gt;
| Boolean value or a formula returning a boolean value.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;string&amp;quot;&amp;gt;string&amp;lt;/span&amp;gt;&lt;br /&gt;
| A text.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;tstring&amp;quot;&amp;gt;tstring&amp;lt;/span&amp;gt;&lt;br /&gt;
| A translatable string.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_tstring&amp;quot;&amp;gt;f_tstring&amp;lt;/span&amp;gt;&lt;br /&gt;
| Formula returning a translatable string.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;function&amp;quot;&amp;gt;function&amp;lt;/span&amp;gt;&lt;br /&gt;
| A string containing a set of function definition for the formula language.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;color&amp;quot;&amp;gt;color&amp;lt;/span&amp;gt;&lt;br /&gt;
| A string which contains the color, this a group of 4 numbers between 0 and 255 separated by commas. The numbers are red component, green component, blue component and alpha.  An alpha of 0 is fully transparent, while an alpha of 255 is fully opaque. Omitted values are set to 0.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_color&amp;quot;&amp;gt;f_color&amp;lt;/span&amp;gt;&lt;br /&gt;
|  A color, or a formula returning a color value.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;font_style&amp;quot;&amp;gt;font_style&amp;lt;/span&amp;gt;&lt;br /&gt;
| A string which contains the style of the font: &lt;br /&gt;
* normal    normal font &lt;br /&gt;
* bold      bold font &lt;br /&gt;
* italic    italic font &lt;br /&gt;
* underline underlined font &lt;br /&gt;
Since SDL has problems combining these styles only one can be picked. Once SDL will allow multiple options, this type will be transformed to a comma separated list. If empty we default to the normal style. Since the render engine is replaced by Pango markup this field will change later on. Note widgets that allow marked up text can use markup to change the font style.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;v_align&amp;quot;&amp;gt;v_align&amp;lt;/span&amp;gt;&lt;br /&gt;
| Vertical alignment; how an item is aligned vertically in the available space. Possible values: &lt;br /&gt;
* top    aligned at the top &lt;br /&gt;
* bottom aligned at the bottom &lt;br /&gt;
* center centered &lt;br /&gt;
When nothing is set or an another value as in the list the item is centered.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;h_align&amp;quot;&amp;gt;h_align&amp;lt;/span&amp;gt;&lt;br /&gt;
| Horizontal alignment; how an item is aligned horizontally in the available space. Possible values: &lt;br /&gt;
* left   aligned at the left side &lt;br /&gt;
* right  aligned at the right side &lt;br /&gt;
* center centered&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;f_h_align&amp;quot;&amp;gt;f_h_align&amp;lt;/span&amp;gt;&lt;br /&gt;
| A horizontal alignment or a formula returning a horizontal alignment.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;border&amp;quot;&amp;gt;border&amp;lt;/span&amp;gt;&lt;br /&gt;
| Comma separated list of borders to use. Possible values: &lt;br /&gt;
* left   border at the left side &lt;br /&gt;
* right  border at the right side &lt;br /&gt;
* top    border at the top &lt;br /&gt;
* bottom border at the bottom &lt;br /&gt;
* all    alias for &amp;quot;left, right, top, bottom&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;scrollbar_mode&amp;quot;&amp;gt;scrollbar_mode&amp;lt;/span&amp;gt;&lt;br /&gt;
| How to show the scrollbar of a widget. Possible values: &lt;br /&gt;
* always       The scrollbar is always shown, regardless whether it's required or not. &lt;br /&gt;
* never        The scrollbar is never shown, even not when needed. (Note when setting this mode dialogs might not properly fit anymore). &lt;br /&gt;
* auto         Shows the scrollbar when needed. The widget will reserve space for the scrollbar, but only show when needed. &lt;br /&gt;
* initial_auto Like auto, but when the scrollbar is not needed the space is not reserved. &lt;br /&gt;
Use auto when the list can be changed dynamically eg the game list in the lobby. For optimization you can also use auto when you really expect a scrollbar, but don't want it to be shown when not needed eg the language list will need a scrollbar on most screens.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;resize_mode&amp;quot;&amp;gt;resize_mode&amp;lt;/span&amp;gt;&lt;br /&gt;
| Determines how an image is resized. Possible values: &lt;br /&gt;
* scale        The image is scaled. &lt;br /&gt;
* stretch      The first row or column of pixels is copied over the entire image. (Can only be used to scale resize in one direction, else falls back to scale.) &lt;br /&gt;
* tile         The image is placed several times until the entire surface is filled. The last images are truncated.&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;vertical-align:top&amp;quot;| &amp;lt;span id=&amp;quot;grow_direction&amp;quot;&amp;gt;grow_direction&amp;lt;/span&amp;gt;&lt;br /&gt;
| Determines how an image is resized. Possible values: &lt;br /&gt;
* scale        The image is scaled. &lt;br /&gt;
* stretch      The first row or column of pixels is copied over the entire image. (Can only be used to scale resize in one direction, else falls back to scale.) &lt;br /&gt;
* tile         The image is placed several times until the entire surface is filled. The last images are truncated.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Section types ==&lt;br /&gt;
For more complex parts, there are sections. Sections contain of several&lt;br /&gt;
lines of WML and can have sub sections. For example a grid has sub sections&lt;br /&gt;
which contain various widgets. Here's the list of sections.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span id=&amp;quot;section&amp;quot;&amp;gt;section&amp;lt;/span&amp;gt;&lt;br /&gt;
| A generic section. The documentation about the section should describe the section in further detail.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span id=&amp;quot;grid&amp;quot;&amp;gt;grid&amp;lt;/span&amp;gt;&lt;br /&gt;
| A grid contains several widgets. (TODO add link to generic grid page.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73937</id>
		<title>GUICanvasWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUICanvasWML&amp;diff=73937"/>
		<updated>2024-11-05T02:30:54Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Circle */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Canvas ==&lt;br /&gt;
A canvas is a blank drawing area on which the user can draw several shapes.&lt;br /&gt;
The drawing is done by adding WML structures to the canvas.&lt;br /&gt;
&lt;br /&gt;
== Global Variables ==&lt;br /&gt;
These variables are available to all shapes inside the canvas, in addition to any local variables they may posess, if any.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#tstring|tstring]]&lt;br /&gt;
| The text to render on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum width available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_maximum_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The maximum height available for the text on the widget.&lt;br /&gt;
|-&lt;br /&gt;
| text_wrap_mode&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| When the text doesn't fit in the available width there are several ways to fix that. This sets which method is used and possible values are the same as [https://docs.gtk.org/Pango/enum.EllipsizeMode.html here], that is, '''0''' (No elllipsization, wrap text instead), '''1''' (ellipsize start of text), '''2''' (ellipsize end of text), '''3''' (ellipsize at the middle). More details (slightly technical) are found at the Pango docs [https://docs.gtk.org/Pango/method.Layout.set_ellipsize.html here].&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#h_align|h_align]]&lt;br /&gt;
| The way the text is aligned inside the canvas.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The size variables are copied to the window and will be determined at&lt;br /&gt;
runtime. This is needed since the main window can be resized and the dialog&lt;br /&gt;
needs to resize accordingly. The following variables are available:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| screen_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| screen_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth main window.&lt;br /&gt;
|-&lt;br /&gt;
| gamemapx_offset&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The distance between left edge of the screen and the game map.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable width of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_width.&lt;br /&gt;
|-&lt;br /&gt;
| gamemap_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The usable height of the Wesnoth gamemap, if no gamemap shown it's the same value as screen_height.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_x&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The x coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| mouse_y&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The y coordinate of the mouse pointer.&lt;br /&gt;
|-&lt;br /&gt;
| window_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window width. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum width. If no maximum is wanted it should be set to the '&amp;quot;(screen_width)&amp;quot;'. - When not equal to 0 its value is the best width for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_width)&amp;quot;'.&lt;br /&gt;
|-&lt;br /&gt;
| window_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The window height. This value has two meanings during the layout phase. This only applies if automatic placement is not enabled. - When set to 0 it should return the wanted maximum height. If no maximum is wanted it should be set to the '&amp;quot;(screen_height)&amp;quot;'. - When not equal to 0 its value is the best height for the window. When the size should remain unchanged it should be set to '&amp;quot;(window_height)&amp;quot;'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note when drawing the valid coordinates are:&amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; width - 1 &amp;lt;br&amp;gt;&lt;br /&gt;
0 -&amp;gt; height -1&lt;br /&gt;
&lt;br /&gt;
Drawing outside this area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Pre commit ==&lt;br /&gt;
This section contains the pre commit functions. These functions will be&lt;br /&gt;
executed before the drawn canvas is applied on top of the normal&lt;br /&gt;
background. There should only be one pre commit section and its order&lt;br /&gt;
regarding the other shapes doesn't matter. The function has effect on the&lt;br /&gt;
entire canvas, it's not possible to affect only a small part of the canvas.&lt;br /&gt;
&lt;br /&gt;
The section can have one of the following subsections.&lt;br /&gt;
&lt;br /&gt;
=== Blur ===&lt;br /&gt;
Blurs the background before applying the canvas. This doesn't make sense&lt;br /&gt;
if the widget isn't semi-transparent.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| depth&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The depth to blur.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Line ==&lt;br /&gt;
Definition of a line. When drawing a line it doesn't get blended on the&lt;br /&gt;
surface but replaces the pixels instead.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y1&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the startpoint.&lt;br /&gt;
|-&lt;br /&gt;
| x2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| y2&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the endpoint.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the line.&lt;br /&gt;
|-&lt;br /&gt;
| thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the line if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Bounded Shape ==&lt;br /&gt;
Common attributes of rectangles, round rectangles and text:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rectangle ==&lt;br /&gt;
Definition of a rectangle. When drawing a rectangle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be added&lt;br /&gt;
later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Rounded Rectangle ==&lt;br /&gt;
Definition of a rounded rectangle shape.&lt;br /&gt;
&lt;br /&gt;
When drawing a rounded rectangle it doesn't get blended on the surface but replaces the pixels instead. A blitting flag might be added later if needed.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| corner_radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the rectangle's corners.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation; this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Circle ==&lt;br /&gt;
Definition of a circle. When drawing a circle it doesn't get blended on&lt;br /&gt;
the surface but replaces the pixels instead. A blitting flag might be&lt;br /&gt;
added later if needed.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the center.&lt;br /&gt;
|-&lt;br /&gt;
| radius&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The radius of the circle if 0 nothing is drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_thickness&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The thickness of the border; if the thickness is zero it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| border_color&lt;br /&gt;
| [[GUIVariable#f_color|f_color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the border; if empty it's not drawn.&lt;br /&gt;
|-&lt;br /&gt;
| fill_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the interior; if omitted it's not drawn.|-&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Drawing outside the area will result in unpredictable results including&lt;br /&gt;
crashing. (That should be fixed, when encountered.)&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
Definition of an image.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the image, if not zero the image will be scaled to the desired width.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the image, if not zero the image will be scaled to the desired height.&lt;br /&gt;
|-&lt;br /&gt;
| resize_mode&lt;br /&gt;
| [[GUIVariable#resize_mode|resize_mode]]&lt;br /&gt;
| scale&lt;br /&gt;
| Determines how an image is scaled to fit the wanted size.&lt;br /&gt;
|-&lt;br /&gt;
| vertical_mirror&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Mirror the image over the vertical axis.&lt;br /&gt;
|-&lt;br /&gt;
| name&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the image.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| image_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image, either the requested width or the natural width of the image. This value can be used to set the x (or y) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image, either the requested height or the natural height of the image. This value can be used to set the y (or x) value of the image. (This means x and y are evaluated after the width and height.)&lt;br /&gt;
|-&lt;br /&gt;
| image_original_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the image as stored on disk, can be used to set x or w (also y and h can be set).&lt;br /&gt;
|-&lt;br /&gt;
| image_original_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the image as stored on disk, can be used to set y or h (also x and y can be set).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text ==&lt;br /&gt;
Definition of text.&lt;br /&gt;
&lt;br /&gt;
Keys:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| x&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The x coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| y&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The y coordinate of the top left corner.&lt;br /&gt;
|-&lt;br /&gt;
| w&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| h&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the text's bounding rectangle.&lt;br /&gt;
|-&lt;br /&gt;
| font_family&lt;br /&gt;
| [[GUIVariable#font_family|font_family]]&lt;br /&gt;
| &amp;quot;sans&amp;quot;&lt;br /&gt;
| The font family used for the text.&lt;br /&gt;
|-&lt;br /&gt;
| font_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The size of the text font.&lt;br /&gt;
|-&lt;br /&gt;
| font_style&lt;br /&gt;
| [[GUIVariable#font_style|font_style]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The style of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment&lt;br /&gt;
| [[GUIVariable#f_h_align|f_h_align]]&lt;br /&gt;
| &amp;quot;left&amp;quot;&lt;br /&gt;
| The alignment of the text.&lt;br /&gt;
|-&lt;br /&gt;
| color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the text.&lt;br /&gt;
|-&lt;br /&gt;
| text&lt;br /&gt;
| [[GUIVariable#f_tstring|f_tstring]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The text to draw (translatable).&lt;br /&gt;
|-&lt;br /&gt;
| text_markup&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Can the text have mark-up?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_aware&lt;br /&gt;
| [[GUIVariable#f_bool|f_bool]]&lt;br /&gt;
| false&lt;br /&gt;
| Is the text link aware?&lt;br /&gt;
|-&lt;br /&gt;
| text_link_color&lt;br /&gt;
| [[GUIVariable#f_string|f_string]]&lt;br /&gt;
| &amp;quot;#ffff00&amp;quot;&lt;br /&gt;
| The color of links in the text&lt;br /&gt;
|-&lt;br /&gt;
| maximum_width&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum width the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_height&lt;br /&gt;
| [[GUIVariable#f_int|f_int]]&lt;br /&gt;
| -1&lt;br /&gt;
| The maximum height the text is allowed to be.&lt;br /&gt;
|-&lt;br /&gt;
| actions&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| WFL code that will be executed when this shape is drawn. In particular, [[FormulaAI_Functions#.27set_var.27_function|set_var]] can be used here to store any variables mentioned in the variables section for global use inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| debug&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Debug message to show upon creation this message is not stored.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE alignment could only be done with the formulas, but now with the&lt;br /&gt;
text_alignment flag as well, older widgets might still use the formulas and&lt;br /&gt;
not all widgets may expose the text alignment yet and when exposed not use&lt;br /&gt;
it yet.&lt;br /&gt;
&lt;br /&gt;
Local Variables:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Variable&lt;br /&gt;
!type&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| text_width&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The width of the rendered text.&lt;br /&gt;
|-&lt;br /&gt;
| text_height&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| The height of the rendered text.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/wesnoth/interface&amp;diff=73934</id>
		<title>LuaAPI/wesnoth/interface</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/wesnoth/interface&amp;diff=73934"/>
		<updated>2024-11-04T13:50:08Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* wesnoth.interface.delay */  - update deprecated example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.15|0}}&lt;br /&gt;
&lt;br /&gt;
The entire interface module is only available in the game. It is not available to plugins or map generators.&lt;br /&gt;
&lt;br /&gt;
== Interface functions ==&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.delay ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.delay'''(''milliseconds'')&lt;br /&gt;
&lt;br /&gt;
Delays the engine for a period of time, specified in milliseconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.delay(500)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.deselect_hex ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.deselect_hex'''()&lt;br /&gt;
&lt;br /&gt;
Reverses any highlight_hex call, leaving all locations unhighlighted. Takes no arguments.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.highlight_hex ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.highlight_hex'''(''x'', ''y'')&lt;br /&gt;
&lt;br /&gt;
Draws an outline around the specified hex.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.select_unit ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.select_unit'''(''x'', ''y'', [''show_movement'', [''fire_events'']])&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.units.select'''(''unit'', [''show_movement'', [''fire_events'']])&lt;br /&gt;
* {{LuaGameOnly}} ''unit'':'''select'''([''show_movement'', [''fire_events'']])&lt;br /&gt;
&lt;br /&gt;
Selects the given unit in the game map as if the player had clicked on it.&lt;br /&gt;
Argument 3: boolean, whether to show the movement range of any unit on that location (def: true)&lt;br /&gt;
Argument 4: boolean, whether to fire any select events (def: false).&lt;br /&gt;
&lt;br /&gt;
This function is available under two different names, but the possible arguments are the same in both cases. In other words, '''wesnoth.units.select''' can be called with a location instead of a unit, and '''wesnoth.interface.select_unit''' can be called with a unit instead of a location.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.select_unit(14, 6, true, true)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If called without arguments, this function deselects the current unit from the map as long as the mouse cursor is not on its hex. It will continue to be displayed on the UI sidebar in any case.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.float_label ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.float_label'''(''x'', ''y'', ''text'')&lt;br /&gt;
&lt;br /&gt;
Pops some text above a map tile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.float_label(unit.x, unit.y, &amp;quot;&amp;lt;span color='#ff0000'&amp;gt;Ouch&amp;lt;/span&amp;gt;&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.get_displayed_unit ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.get_displayed_unit'''() → ''unit''&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.units.get_hovered'''() → ''unit''&lt;br /&gt;
&lt;br /&gt;
Returns a proxy to the unit currently displayed in the side pane of the user interface, if any.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local name = tostring(wesnoth.interface.get_displayed_unit().name)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.get_hovered_hex ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.get_hovered_hex'''() → ''x'', ''y''&lt;br /&gt;
&lt;br /&gt;
Returns the two coordinates of the currently hovered tile, that is, where the mouse cursor is located. This is mostly useful for defining command-mode helpers.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.get_selected_hex ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.get_selected_hex'''() → ''x'', ''y''&lt;br /&gt;
&lt;br /&gt;
Returns the two coordinates of the currently selected (highlighted) tile. This is mostly useful for defining command-mode helpers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function chg_unit(attr, val)&lt;br /&gt;
   local x, y = wesnoth.interface.get_selected_hex()&lt;br /&gt;
   if not x then wesnoth.message(&amp;quot;Error&amp;quot;, &amp;quot;No unit selected.&amp;quot;); return end&lt;br /&gt;
   wesnoth.units.modify({ x = x, y = y }, { [attr] = val })&lt;br /&gt;
end&lt;br /&gt;
-- Function chg_unit can be used in command mode to modify unit attributes on the fly:&lt;br /&gt;
--   :lua chg_unit(&amp;quot;status.poisoned&amp;quot;, true)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.get_viewing_side ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.get_viewing_side'''() &amp;amp;rarr; ''side'', ''full_vision''&lt;br /&gt;
&lt;br /&gt;
Returns the viewing side of the current client in a multiplayer game.&lt;br /&gt;
&lt;br /&gt;
For a player participating in the game, this will always be the side that they control, or, if they control multiple sides, the one they most recently had control over. However, for an observer client, this will return the currently-active side instead.&lt;br /&gt;
&lt;br /&gt;
The second return value indicates whether the current client has full vision. This can only happen in replays or for observers.&lt;br /&gt;
&lt;br /&gt;
For obvious reasons, use of this function can easily cause out-of-sync errors. Use with care.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.lock===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.lock'''(''lock'')&lt;br /&gt;
&lt;br /&gt;
Locks or unlocks gamemap view scrolling for human players. If true is passed as the first parameter, the view is locked; pass false to unlock.&lt;br /&gt;
&lt;br /&gt;
Human players cannot scroll the gamemap view as long as it is locked, but Lua or WML actions such as wesnoth.scroll_to_hex still can; the locked/unlocked state is preserved when saving the current game. This feature is generally intended to be used in cutscenes to prevent the player scrolling away from scripted actions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.lock_view(true)&lt;br /&gt;
wesnoth.interface.scroll_to_hex(12, 14, false, true)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.is_locked ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.is_locked'''() → ''locked?''&lt;br /&gt;
&lt;br /&gt;
Returns a boolean indicating whether gamemap view scrolling is currently locked.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.scroll_to_hex ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.scroll_to_hex'''(''x'', ''y'', [''only_if_visible'', [''instant'', [''only_if_needed'']]])&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.units.scroll_to'''(''unit'', [''only_if_visible'', [''instant'', [''only_if_needed'']]])&lt;br /&gt;
* {{LuaGameOnly}} ''unit'':'''scroll_to'''([''only_if_visible'', [''instant'', [''only_if_needed'']]])&lt;br /&gt;
&lt;br /&gt;
Scrolls the map to the given location. If true is passed as the third parameter, scrolling is disabled if the tile is hidden under the fog. If true is passed as the fourth parameter, the view instantly warps to the location regardless of the scroll speed setting in Preferences. If true is passed as the fifth parameter, no scrolling occurs if the target location is already visible onscreen. It is also possible to pass a unit instead of a pair of tile coordinates (regardless of which module the function is called from).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local u = wesnoth.units.get &amp;quot;hero&amp;quot;&lt;br /&gt;
u:scroll_to()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.scroll ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.scroll'''(''dx'', ''dy'')&lt;br /&gt;
&lt;br /&gt;
Scrolls the map by the given amount, which may be either positive or negative.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.zoom ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.zoom'''(''factor'', [''relative'']) → ''new_zoom''&lt;br /&gt;
&lt;br /&gt;
Changes the zoom level of the map. If relative is false, which is the default, it simply sets the zoom level. If relative is true, it zooms relative to the current zoom level. So, for example, if the zoom level is currently 0.5, then&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua inline&amp;gt;wesnoth.zoom(2)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sets it to 2, while&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua inline&amp;gt;wesnoth.zoom(2, true)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
sets it to 1 (2 * 0.5).&lt;br /&gt;
&lt;br /&gt;
This function also returns the resulting zoom level. Because of this, you can call&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua inline&amp;gt;wesnoth.zoom(1, true)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to simply get the current zoom level.&lt;br /&gt;
&lt;br /&gt;
Note that this function cannot zoom to a level that the user would not be able to reach from the UI. Attempting to do so will simply select the nearest allowed zoom level.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.skip_messages ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.skip_messages'''([''skip?''])&lt;br /&gt;
&lt;br /&gt;
Sets the skip messages flag. By default it sets it to true, but you can also pass false to unset the flag.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.is_skipping_messages ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.is_skipping_messages'''()&lt;br /&gt;
&lt;br /&gt;
Returns true if messages are currently being skipped, for example because the player has chosen to skip replay, or has pressed escape to dismiss a message.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.add_chat_message ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.add_chat_message'''([''speaker'',] ''message'')&lt;br /&gt;
&lt;br /&gt;
Displays a string in the onscreen chat. The chat line speaker is &amp;quot;Lua&amp;quot; by default, but it can be changed by passing a string before the message.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.add_chat_message &amp;quot;Hello World!&amp;quot; -- will result in &amp;quot;&amp;lt;Lua&amp;gt; Hello World!&amp;quot;&lt;br /&gt;
wesnoth.interface.add_chat_message(&amp;quot;Big Brother&amp;quot;, &amp;quot;I'm watching you.&amp;quot;) -- will result in &amp;quot;&amp;lt;Big Brother&amp;gt; I'm watching you.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also [[LuaAPI/wml#wml.error|wml.error]] for displaying error messages.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.clear_chat_messages ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.clear_chat_messages'''()&lt;br /&gt;
&lt;br /&gt;
Removes all messages from the onscreen chat, including error messages.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.add_item_image ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.add_item_image'''(''location'', ''filename'')&lt;br /&gt;
&lt;br /&gt;
Places an image at a given location and registers it as a WML ''[item]'' would do, so that it can be restored after save/load. Note that the location must be passed as separate x and y coordinates, as in the example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.add_item_image(17, 42, &amp;quot;items/orcish-flag.png&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.add_item_halo ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.add_item_halo'''(''location'', ''filename'')&lt;br /&gt;
&lt;br /&gt;
Behaves the same as [[#wesnoth.interface.add_item_image]] but for halos.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.remove_item ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.remove_item'''(''location'', [''filename''])&lt;br /&gt;
&lt;br /&gt;
Removes an overlay set by [[#wesnoth.interface.add_item_image]] or [[#wesnoth.interface.add_item_halo]]. If no filename is provided, all the overlays on a given tile are removed. Note that the location must be passed as separate x and y coordinates, as in the example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.remove_item(17, 42, &amp;quot;items/orcish-flag.png&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.get_items ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.get_items'''(''location'') &amp;amp;rarr; ''array of item tables''&lt;br /&gt;
&lt;br /&gt;
Get all items placed on the specified location. Note that the location must be passed as separate x and y coordinates.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.add_hex_overlay ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.add_hex_overlay'''(''location'', ''item_wml'')&lt;br /&gt;
&lt;br /&gt;
Places a hex overlay (either an image or a halo) on the given location. The overlay is described by a table supporting the same fields as [[InterfaceActionsWML|[item]]]. This is a lower-level version of the item functions above. Note that the overlay is not kept over save/load cycles.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.add_hex_overlay(17, 42, { image = &amp;quot;items/orcish-flag.png&amp;quot; })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.remove_hex_overlay ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.remove_hex_overlay'''(''location'', [''filename''])&lt;br /&gt;
&lt;br /&gt;
Removes all the overlays at the given location, including any added by '''wesnoth.interface.add_item_halo''' or '''wesnoth.interface.add_item_image''' (however, such a removal will not be kept over save/load cycles). If a filename is passed as a third argument, only this overlay (either image or halo) is removed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wesnoth.interface.remove_hex_overlay(17, 42, &amp;quot;items/orcish-flag.png&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.end_turn ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.end_turn'''([''next_side''])&lt;br /&gt;
&lt;br /&gt;
Immediately ends the current side's turn. By default, the next sequential side will gain control, but if you pass an argument that side gains control instead.&lt;br /&gt;
&lt;br /&gt;
The ''next_side'' can either be a valid side number, or a valid side number plus the total number of sides in the scenario. In the latter case, this function also increases the turn counter by 1.&lt;br /&gt;
&lt;br /&gt;
Using this, it's entirely possible to pass control around without ever increasing the turn counter.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.allow_end_turn ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.allow_end_turn'''(''allow'')&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.allow_end_turn'''(''reason'')&lt;br /&gt;
&lt;br /&gt;
Enables or disables ending the turn in the UI. You can optionally pass a translatable string to show to the player if they attempt to do so anyway. It will be shown to the player without any additional framing, so it should normally be phrased similar to &amp;quot;You cannot end your turn because...&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To allow the player to end their turn again, just pass '''true'''. If you pass '''false''', a default message will be shown.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.color_adjust ===&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.color_adjust'''(''red'', ''green'', ''blue'')&lt;br /&gt;
&lt;br /&gt;
Adjust the screen tint. (0,0,0) is no tint, and possible values range from -255 to 255.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.add_overlay_text ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|3}}&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.add_overlay_text'''(''text'' [, ''options'']) &amp;amp;rarr; ''text handle''&lt;br /&gt;
&lt;br /&gt;
Adds a text overlay to the screen that does not move with the map. [[Pango formatting]] is supported. The ''options'' table supports the following keys:&lt;br /&gt;
&lt;br /&gt;
* ''size'' - The font size.&lt;br /&gt;
* ''max_width'' - Sets the maximum width the text can occupy on the screen, either in screen units (pixels) or as a percentage (a string ending in &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;). If the text is too long to fit in that width, it will automatically be word-wrapped. Defaults to 100%.&lt;br /&gt;
* ''color'' - The text color, either as a six-digit hex string (no leading &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt;) or an array of three integers (red, green, and blue).&lt;br /&gt;
* ''bgcolor'' - If present, a background in this color is placed behind the text to enhance readability. This works like the background behind chat messages, but can be any colour. It is formatted the same as ''color''. If omitted, the background is fully transparent (ie, there is no background).&lt;br /&gt;
* ''bgalpha'' - If a background colour is specified, this sets its transparency. The default is fully opaque.&lt;br /&gt;
* ''duration'' - How long the text should be displayed, in milliseconds, or the string &amp;lt;syntaxhighlight lang=lua inline&amp;gt;'unlimited'&amp;lt;/syntaxhighlight&amp;gt; for an infinite duration. Defaults to two seconds.&lt;br /&gt;
* ''fade_time'' - When the label is removed, either explicitly or because its duration expired, this is the time it takes to fade out, in milliseconds. A value of 0 means the label disappears instantly. Defaults to 100.&lt;br /&gt;
* ''halign'' - Where to anchor the text horizontally on the screen. Must be one of &amp;lt;syntaxhighlight lang=lua inline&amp;gt;'left', 'center', 'right'&amp;lt;/syntaxhighlight&amp;gt;.&lt;br /&gt;
* ''valign'' - Where to anchor the text vertically on the screen. Must be one of &amp;lt;syntaxhighlight lang=lua inline&amp;gt;'top', 'center', 'bottom'&amp;lt;/syntaxhighlight&amp;gt;.&lt;br /&gt;
* ''location'' - The screen offset where the text should be placed, relative to the specified anchor. Defaults to (0,0).&lt;br /&gt;
&lt;br /&gt;
The text handle returned from this function supports the following method calls:&lt;br /&gt;
&lt;br /&gt;
* ''handle'':'''move'''(''x'', ''y'')&lt;br /&gt;
&lt;br /&gt;
Moves the text to a new location on the screen. The provided ''x'' and ''y'' are offsets from its current location.&lt;br /&gt;
&lt;br /&gt;
* ''handle'':'''remove'''([''fade_time''])&lt;br /&gt;
&lt;br /&gt;
Remove the text from the screen, optionally overriding the fade-out time.&lt;br /&gt;
&lt;br /&gt;
* ''handle'':'''replace'''(''text'', ''options'') &amp;amp;rarr; ''handle''&lt;br /&gt;
&lt;br /&gt;
Replaces the text with new text. Options are the same as in ''add_overlay_text'', and the returned handle is the same one.&lt;br /&gt;
&lt;br /&gt;
=== wesnoth.interface.handle_user_interact ===&lt;br /&gt;
&lt;br /&gt;
{{DevFeature1.17|6}}&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.handle_user_interact'''()&lt;br /&gt;
&lt;br /&gt;
Handle user interaction with the game interface. This can be inserted into Lua code that takes a long time to execute in order to prevent the user interface from freezing.&lt;br /&gt;
&lt;br /&gt;
== wesnoth.interface.game_display ==&lt;br /&gt;
&lt;br /&gt;
* {{LuaGameOnly}} '''wesnoth.interface.game_display'''.''theme_item'' &amp;amp;harr; '''function'''() &amp;amp;rarr; ''wml table of theme elements''&lt;br /&gt;
&lt;br /&gt;
This is an associative table linking item names to functions that describe the content of the in-game user interface. These functions are called with no arguments whenever the user interface is refreshed, and must return a WML table containing '''[element]''' children. Each subtag shall contain either a '''text''' or an '''image''' field that is displayed to the user. It can also contain a '''tooltip''' field that is displayed to the user when moused over, and a '''help''' field that points to the help section that is displayed when the user clicks on the theme item.&lt;br /&gt;
&lt;br /&gt;
Note that the '''wesnoth.interface.game_display''' cannot be iterated using '''pairs''' or '''next''' to retrieve the items from the current theme. However, built-in items ''can'' be recovered as long as their name is known. The example below shows how to modify the ''unit_status'' item to display a custom status:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local old_unit_status = wesnoth.interface.game_display.unit_status&lt;br /&gt;
function wesnoth.interface.game_display.unit_status()&lt;br /&gt;
    local _ = wesnoth.textdomain &amp;quot;mydomain&amp;quot;&lt;br /&gt;
    local u = wesnoth.interface.get_displayed_unit()&lt;br /&gt;
    if not u then return {} end&lt;br /&gt;
    local s = old_unit_status()&lt;br /&gt;
    if u.status.entangled then&lt;br /&gt;
        table.insert(s, wml.tag.element {&lt;br /&gt;
            image = &amp;quot;entangled.png&amp;quot;,&lt;br /&gt;
            tooltip = _&amp;quot;entangled: This unit is entangled. It cannot move but it can still attack.&amp;quot;&lt;br /&gt;
        })&lt;br /&gt;
    end&lt;br /&gt;
    return s&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The things that would need to be to modified in the above code are:&lt;br /&gt;
&lt;br /&gt;
* the domain of your addon (&amp;quot;mydomain&amp;quot;), assuming that you are using translations. Otherwise just remove the underscore in the tooltip line.&lt;br /&gt;
* the name of the status (u.status.entangled). Note that if the attribute happens to be inside [variables], so be it: u.variables.whatever.&lt;br /&gt;
* the path to the image (&amp;quot;entangled.png&amp;quot;).&lt;br /&gt;
* the tooltip of the status (&amp;quot;entangled: This unit ...&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
The following is a list of valid entries in '''wesnoth.interface.game_display''' which will have an effect in the game, together with sample output and a brief description of their use.&lt;br /&gt;
&lt;br /&gt;
=== unit_name ===&lt;br /&gt;
&lt;br /&gt;
Shows the name of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_type ===&lt;br /&gt;
&lt;br /&gt;
Shows the type of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_race ===&lt;br /&gt;
&lt;br /&gt;
Shows the race of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_side ===&lt;br /&gt;
&lt;br /&gt;
Shows the side number and team color of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_level ===&lt;br /&gt;
&lt;br /&gt;
Shows the level of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_amla ===&lt;br /&gt;
&lt;br /&gt;
Similar to unit_advancement_options but shows AMLAs only.&lt;br /&gt;
&lt;br /&gt;
=== unit_traits ===&lt;br /&gt;
&lt;br /&gt;
Shows the list of trait names for the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_status ===&lt;br /&gt;
&lt;br /&gt;
Shows the status icons for statuses afflicting the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_alignment ===&lt;br /&gt;
&lt;br /&gt;
Shows the alignment of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_abilities ===&lt;br /&gt;
&lt;br /&gt;
Shows the ability names of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_hp ===&lt;br /&gt;
&lt;br /&gt;
Shows the current and maximum hit points of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_xp ===&lt;br /&gt;
&lt;br /&gt;
Shows the current and target experience points of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_advancement_options ===&lt;br /&gt;
&lt;br /&gt;
Shows the options the unit the mouse is hovering over has for advancement, including both level ups and AMLAs. This item is not used in the default theme.&lt;br /&gt;
&lt;br /&gt;
=== unit_defense ===&lt;br /&gt;
&lt;br /&gt;
Shows the defense of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_vision ===&lt;br /&gt;
&lt;br /&gt;
Shows the current and maximum vision points of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_moves ===&lt;br /&gt;
&lt;br /&gt;
Shows the current and maximum movement points of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_weapons ===&lt;br /&gt;
&lt;br /&gt;
Shows the available weapons of the unit the mouse is hovering over. The default generator expresses each weapon line (basic details, specials, etc) as a separate &amp;lt;code&amp;gt;element&amp;lt;/code&amp;gt;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[element]&lt;br /&gt;
  image=&amp;quot;melee.png&amp;quot;&lt;br /&gt;
  tooltip=&amp;quot;...stuff...&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
[element]&lt;br /&gt;
  image=&amp;quot;arcane.png&amp;quot;&lt;br /&gt;
  tooltip=&amp;quot;...stuff...&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
[element]&lt;br /&gt;
  text=&amp;quot;6×3 holy sword&amp;quot;&lt;br /&gt;
  tooltip=&amp;quot;...stuff...&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
[element]&lt;br /&gt;
  # This is empty if the range and type icons both exist.&lt;br /&gt;
  text=&amp;quot;melee-arcane&amp;quot;&lt;br /&gt;
  tooltip=&amp;quot;...stuff...&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
# If the weapon has accuracy or parry...&lt;br /&gt;
[element]&lt;br /&gt;
  text=&amp;quot;+20%/-10%&amp;quot;&lt;br /&gt;
  tooltip=&amp;quot;Accuracy: +20%&lt;br /&gt;
Parry: -10%&lt;br /&gt;
&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
# If the weapon has special abilities...&lt;br /&gt;
[element]&lt;br /&gt;
  text=&amp;quot;magical&amp;quot;&lt;br /&gt;
  tooltip=&amp;quot;...stuff...&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== unit_image ===&lt;br /&gt;
&lt;br /&gt;
Shows the sprite of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== unit_profile ===&lt;br /&gt;
&lt;br /&gt;
Shows the portrait of the unit the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== selected_unit ===&lt;br /&gt;
&lt;br /&gt;
Nearly every item beginning with '''unit_''' has a corresponding item beginning with '''selected_unit_''', which describes the currently-selected unit (if any) rather than the unit the mouse is hovering over. These items are not used in the default theme.&lt;br /&gt;
&lt;br /&gt;
There is no '''selected_unit_amla''' however.&lt;br /&gt;
&lt;br /&gt;
=== highlighted_unit_weapons ===&lt;br /&gt;
&lt;br /&gt;
This is almost the same as '''selected_unit_weapons''' but with slightly different logic of choosing which unit to show.&lt;br /&gt;
&lt;br /&gt;
=== tod_stats and selected_tod_stats ===&lt;br /&gt;
&lt;br /&gt;
Shows the time of day stats for the hex the mouse is hovering over or the hex the selected unit is on. The time of day stats shows the counter of your position in the schedule as well as the entire cycle.&lt;br /&gt;
&lt;br /&gt;
=== time_of_day and selected_time_of_day ===&lt;br /&gt;
&lt;br /&gt;
Shows the time of day image for the hex the mouse is hovering over or the hex the selected unit is on.&lt;br /&gt;
&lt;br /&gt;
=== unit_box ===&lt;br /&gt;
&lt;br /&gt;
This is an experimental item that combines a unit display and the time of day.&lt;br /&gt;
&lt;br /&gt;
=== turn ===&lt;br /&gt;
&lt;br /&gt;
Shows the current turn count.&lt;br /&gt;
&lt;br /&gt;
=== gold ===&lt;br /&gt;
&lt;br /&gt;
Shows the amount of gold for the active side.&lt;br /&gt;
&lt;br /&gt;
=== villages ===&lt;br /&gt;
&lt;br /&gt;
Shows the number of villages owned by the active side.&lt;br /&gt;
&lt;br /&gt;
=== num_units ===&lt;br /&gt;
&lt;br /&gt;
Shows the number of units owned by the active side.&lt;br /&gt;
&lt;br /&gt;
=== upkeep ===&lt;br /&gt;
&lt;br /&gt;
Shows the upkeep and expenses for the active side.&lt;br /&gt;
&lt;br /&gt;
=== income ===&lt;br /&gt;
&lt;br /&gt;
Shows the income for the active side&lt;br /&gt;
&lt;br /&gt;
=== terrain_info ===&lt;br /&gt;
&lt;br /&gt;
Shows the icons of the terrain on hex the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== terrain &amp;lt;!--and selected_terrain--&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- selected_terrain commented out here because at time of last edit it was commented out in the source code --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Shows the name of the terrain on the hex the mouse is hovering over&amp;lt;!-- or the hex the selected unit is on--&amp;gt;. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[element]&lt;br /&gt;
  text=&amp;quot;Grassland (Flat)&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== position ===&lt;br /&gt;
&lt;br /&gt;
Shows the map coordinates of the hex the mouse is hovering over.&lt;br /&gt;
&lt;br /&gt;
=== zoom_level ===&lt;br /&gt;
&lt;br /&gt;
Shows the zoom level as a percentage. This item is not used in the default theme.&lt;br /&gt;
&lt;br /&gt;
=== side_playing ===&lt;br /&gt;
&lt;br /&gt;
Shows the active side's flag.&lt;br /&gt;
&lt;br /&gt;
=== observers ===&lt;br /&gt;
&lt;br /&gt;
When there is no observer, it returns an empty table. When there are observers, it returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[element]&lt;br /&gt;
  tooltip=&amp;quot;Observers&lt;br /&gt;
&amp;lt;observer1&amp;gt;&lt;br /&gt;
&amp;lt;observer2&amp;gt;&lt;br /&gt;
&amp;quot;&lt;br /&gt;
  image=&amp;quot;misc/eye.png&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== report_clock ===&lt;br /&gt;
&lt;br /&gt;
This returns the current time in HH:MM format according to the user's preferences, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[element]&lt;br /&gt;
  text=&amp;quot;22:32&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== report_countdown ===&lt;br /&gt;
&lt;br /&gt;
This returns the current chess-timer countdown in MM:SS format for the player's turn, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[element]&lt;br /&gt;
  text=&amp;quot;12:43&amp;quot;&lt;br /&gt;
[/element]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Depending on the time limit, the text may also be colored using [[Pango formatting|Pango markup]].&lt;br /&gt;
&lt;br /&gt;
If there is no time limit set then it forwards to [[#wesnoth.interface.game_display.report_clock|report_clock]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73921</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73921"/>
		<updated>2024-11-01T23:42:15Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Adding a little flavor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    wml.parse(wml.tostring({wml.tag.resolution(dialogDefinition)}), &amp;quot;schema/gui_window.cfg&amp;quot;) -- schema validation errors will go to log&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this example, just before we invoke gui.show_dialog(), we use [[LuaAPI/wml#wml.parse|wml.parse()]] to validate our input against the GUI2 window schema.  If we've misspelled something, or placed a key in the wrong place (like placing a border in a widget instead of a column), etc, an error such as '''error validation: Invalid key 'garbage=' in tag [resolution]''' will be written to the wesnoth log.&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can create many levels of grids inside grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.  With a grid listbox, items are added horizontally with the list wrapping to a new line as necessary.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73919</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73919"/>
		<updated>2024-11-01T21:13:54Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Adding a little flavor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    wml.parse(wml.tostring({{&amp;quot;resolution&amp;quot;, dialogDefinition}}), &amp;quot;schema/gui_window.cfg&amp;quot;) -- schema validation errors will go to log&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this example, just before we invoke gui.show_dialog(), we use [[LuaAPI/wml#wml.parse|wml.parse()]] to validate our input against the GUI2 window schema.  If we've misspelled something, or placed a key in the wrong place (like placing a border in a widget instead of a column), etc, an error such as '''error validation: Invalid key 'garbage=' in tag [resolution]''' will be written to the wesnoth log.&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can create many levels of grids inside grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.  With a grid listbox, items are added horizontally with the list wrapping to a new line as necessary.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73918</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73918"/>
		<updated>2024-11-01T20:53:55Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Adding a little flavor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    wml.parse(wml.tostring({{&amp;quot;resolution&amp;quot;, dialogDefinition}}), &amp;quot;schema/gui_window.cfg&amp;quot;) -- schema validation errors will go to log&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can create many levels of grids inside grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.  With a grid listbox, items are added horizontally with the list wrapping to a new line as necessary.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73917</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73917"/>
		<updated>2024-11-01T20:51:54Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can create many levels of grids inside grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.  With a grid listbox, items are added horizontally with the list wrapping to a new line as necessary.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73916</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73916"/>
		<updated>2024-11-01T20:46:33Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* And a bit more */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can create many levels of grids inside grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.  With a grid listbox, items are added horizontally with the list wrapping to a new line as necessary.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73914</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73914"/>
		<updated>2024-10-30T23:49:51Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Listbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.  With a grid listbox, items are added horizontally with the list wrapping to a new line as necessary.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73903</id>
		<title>LuaAPI/types/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73903"/>
		<updated>2024-10-26T00:44:09Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Widget Attributes */ - change &amp;quot;All&amp;quot; to &amp;quot;Most&amp;quot; for attributes 'only' available to styled_widget&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The '''widget''' userdata offers access to a widget of a GUI2 dialog. While there is only one type of widget userdata that covers all widgets including the window itself, the properties of a widget userdata are different for each type of widget. Indexing a widget's userdata can either be used to access a child widget or to set or get a property of a widget. Some properties are read-only or write-only; the properties depend on the type of the widget.&lt;br /&gt;
&lt;br /&gt;
An example of accessing a child widget:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function preshow(dialog)&lt;br /&gt;
  local okay_button = dialog.okay_button&lt;br /&gt;
  -- okay_button is now a handle to the the widget's child with the id 'okay_button' &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widget Attributes ==&lt;br /&gt;
&lt;br /&gt;
=== selected ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected''' &amp;amp;harr; ''boolean''&lt;br /&gt;
* Available on: '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
Whether the item is selected or not. Note that this should only be used for widgets that have only 2 states. In particular, there exist 3-State toggle_buttons (for example in listbox headers). For those, selected_index must be used instead.&lt;br /&gt;
&lt;br /&gt;
=== selected_index ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_index''' &amp;amp;harr; ''index''&lt;br /&gt;
* Available on: '''[listbox]''', '''[multi_page]''', '''[stacked_widget]''', '''[menu_button]''', '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
The selected index of the item. For '''[toggle_button]''' and '''[toggle_panel]''', this is the same as '''selected''' only encoded as a number (1 for false or 2 for true) instead of a boolean.&lt;br /&gt;
&lt;br /&gt;
For a  '''[listbox]'''with '''has_maximum=false''' and more than one item selected, reading '''selected_index''' will return the first selected index.&lt;br /&gt;
&lt;br /&gt;
For a '''[stacked_widget]''', 0 represents all layers being visible.  If one or more (but not all) layers are visible, reading '''selected_index''' returns the layer most recently made visible.  Writing to '''selected_index''' will make the specified layer (or all layers if 0 is specified) visible.&lt;br /&gt;
&lt;br /&gt;
=== text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''text''' &amp;amp;harr; ''text''&lt;br /&gt;
* Available on: '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
The text of the textbox.&lt;br /&gt;
&lt;br /&gt;
=== value ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''value''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[slider]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the slider.&lt;br /&gt;
&lt;br /&gt;
=== percentage ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''percentage''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[progress_bar]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the progress bar, between 0 and 100.&lt;br /&gt;
&lt;br /&gt;
=== selected_item_path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_item_path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view]'''&lt;br /&gt;
&lt;br /&gt;
A table describing the currently selected node. If for example, in the following treeview, Item 9 is selected, the result will be {2,1,3}.&lt;br /&gt;
&lt;br /&gt;
 +Section1&lt;br /&gt;
  +Subsection11&lt;br /&gt;
   *Item1&lt;br /&gt;
   *Item2&lt;br /&gt;
   *Item3&lt;br /&gt;
  +Subsection12&lt;br /&gt;
   *Item4&lt;br /&gt;
   *Item5&lt;br /&gt;
   *Item6&lt;br /&gt;
 +Section2&lt;br /&gt;
  +Subsection21&lt;br /&gt;
   *Item7&lt;br /&gt;
   *Item8&lt;br /&gt;
   *Item9&lt;br /&gt;
  +Subsection22&lt;br /&gt;
   *Item10&lt;br /&gt;
   *Item11&lt;br /&gt;
   *Item12&lt;br /&gt;
&lt;br /&gt;
=== path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
A table describing this node in the overall treeview. See [[#selected_item_path|selected_item_path]] for the meaning of the table..&lt;br /&gt;
&lt;br /&gt;
=== unfolded ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unfolded''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
Control whether a tree node is currently expanded or not.&lt;br /&gt;
&lt;br /&gt;
=== unit ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unit''' &amp;amp;larr; ''unit or unit type''&lt;br /&gt;
* Available on: '''[unit_preview_pane]'''&lt;br /&gt;
&lt;br /&gt;
Change the displayed unit or unit type in the preview pane.&lt;br /&gt;
&lt;br /&gt;
=== item_count ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''item_count''' &amp;amp;rarr; ''number of items''&lt;br /&gt;
* Available on: '''[multi_page]''', '''[listbox]'''&lt;br /&gt;
&lt;br /&gt;
The number of items in the container widget.&lt;br /&gt;
&lt;br /&gt;
=== use_markup ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''use_markup''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Sets whether the widget's label will parse [[Pango formatting]].&lt;br /&gt;
&lt;br /&gt;
=== label ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''label''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]''', '''[image]'''&lt;br /&gt;
&lt;br /&gt;
The widget's label. Technically this is a special string used in the widget's wml definition. It usually does what one would expect, but also sets the image for '''image''' widgets.  For '''[text_box]''', use '''text''' for initial values.&lt;br /&gt;
&lt;br /&gt;
=== marked_up_text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''marked_up_text''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Shortcut for setting label and use_markup=yes.&lt;br /&gt;
&lt;br /&gt;
=== enabled ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''enabled''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
=== tooltip ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''tooltip''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
=== visible ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''visible''' &amp;amp;larr; ''visibility string''&lt;br /&gt;
* Available on: Most widgets&lt;br /&gt;
&lt;br /&gt;
Determines whether the widget is visible onscreen. The following visibility statuses are recognized:&lt;br /&gt;
{| clasS=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! String value !! Boolean shorthand !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| visible || true || The widget is visible and handles events.&lt;br /&gt;
|-&lt;br /&gt;
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.&lt;br /&gt;
|-&lt;br /&gt;
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''type''' &amp;amp;rarr; ''string''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Returns a string specifying the type of the widget.&lt;br /&gt;
&lt;br /&gt;
== Widget callbacks ==&lt;br /&gt;
&lt;br /&gt;
=== on_modified ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_modified''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: Most widgets, in particular '''[slider]''', '''[toggle_button]''', '''[listbox]''', '''[menu_button]''', '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user changes the value of the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_left_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_left_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_button_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_button_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: '''[button]''', '''[repeating_button]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the button. This can differ from '''on_left_click''', depending on the type of widget. For example, on a '''[repeating_button]''' it will fire multiple times if the user holds the mouse button down.&lt;br /&gt;
&lt;br /&gt;
== Widget methods ==&lt;br /&gt;
&lt;br /&gt;
Any function defined in the [[LuaAPI/gui/widget|gui.widget]] module and taking a widget as its first parameter can be called as a method of a widget. This includes any functions that are added to the module by user code. Note that these methods are available even if the widget itself doesn't support that function, so in some cases it may be necessary to check '''widget.type''' befor calling the method.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73902</id>
		<title>LuaAPI/types/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/types/widget&amp;diff=73902"/>
		<updated>2024-10-26T00:35:49Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* selected_index */ - when multiple items/layers selected&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;tright&amp;quot;&amp;gt; __TOC__ &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The '''widget''' userdata offers access to a widget of a GUI2 dialog. While there is only one type of widget userdata that covers all widgets including the window itself, the properties of a widget userdata are different for each type of widget. Indexing a widget's userdata can either be used to access a child widget or to set or get a property of a widget. Some properties are read-only or write-only; the properties depend on the type of the widget.&lt;br /&gt;
&lt;br /&gt;
An example of accessing a child widget:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function preshow(dialog)&lt;br /&gt;
  local okay_button = dialog.okay_button&lt;br /&gt;
  -- okay_button is now a handle to the the widget's child with the id 'okay_button' &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widget Attributes ==&lt;br /&gt;
&lt;br /&gt;
=== selected ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected''' &amp;amp;harr; ''boolean''&lt;br /&gt;
* Available on: '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
Whether the item is selected or not. Note that this should only be used for widgets that have only 2 states. In particular, there exist 3-State toggle_buttons (for example in listbox headers). For those, selected_index must be used instead.&lt;br /&gt;
&lt;br /&gt;
=== selected_index ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_index''' &amp;amp;harr; ''index''&lt;br /&gt;
* Available on: '''[listbox]''', '''[multi_page]''', '''[stacked_widget]''', '''[menu_button]''', '''[toggle_button]''', '''[toggle_panel]'''&lt;br /&gt;
&lt;br /&gt;
The selected index of the item. For '''[toggle_button]''' and '''[toggle_panel]''', this is the same as '''selected''' only encoded as a number (1 for false or 2 for true) instead of a boolean.&lt;br /&gt;
&lt;br /&gt;
For a  '''[listbox]'''with '''has_maximum=false''' and more than one item selected, reading '''selected_index''' will return the first selected index.&lt;br /&gt;
&lt;br /&gt;
For a '''[stacked_widget]''', 0 represents all layers being visible.  If one or more (but not all) layers are visible, reading '''selected_index''' returns the layer most recently made visible.  Writing to '''selected_index''' will make the specified layer (or all layers if 0 is specified) visible.&lt;br /&gt;
&lt;br /&gt;
=== text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''text''' &amp;amp;harr; ''text''&lt;br /&gt;
* Available on: '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
The text of the textbox.&lt;br /&gt;
&lt;br /&gt;
=== value ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''value''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[slider]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the slider.&lt;br /&gt;
&lt;br /&gt;
=== percentage ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''percentage''' &amp;amp;harr; ''position''&lt;br /&gt;
* Available on: '''[progress_bar]'''&lt;br /&gt;
&lt;br /&gt;
The current position of the progress bar, between 0 and 100.&lt;br /&gt;
&lt;br /&gt;
=== selected_item_path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''selected_item_path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view]'''&lt;br /&gt;
&lt;br /&gt;
A table describing the currently selected node. If for example, in the following treeview, Item 9 is selected, the result will be {2,1,3}.&lt;br /&gt;
&lt;br /&gt;
 +Section1&lt;br /&gt;
  +Subsection11&lt;br /&gt;
   *Item1&lt;br /&gt;
   *Item2&lt;br /&gt;
   *Item3&lt;br /&gt;
  +Subsection12&lt;br /&gt;
   *Item4&lt;br /&gt;
   *Item5&lt;br /&gt;
   *Item6&lt;br /&gt;
 +Section2&lt;br /&gt;
  +Subsection21&lt;br /&gt;
   *Item7&lt;br /&gt;
   *Item8&lt;br /&gt;
   *Item9&lt;br /&gt;
  +Subsection22&lt;br /&gt;
   *Item10&lt;br /&gt;
   *Item11&lt;br /&gt;
   *Item12&lt;br /&gt;
&lt;br /&gt;
=== path ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''path''' &amp;amp;rarr; ''array of indices''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
A table describing this node in the overall treeview. See [[#selected_item_path|selected_item_path]] for the meaning of the table..&lt;br /&gt;
&lt;br /&gt;
=== unfolded ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unfolded''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: '''[tree_view_node]'''&lt;br /&gt;
&lt;br /&gt;
Control whether a tree node is currently expanded or not.&lt;br /&gt;
&lt;br /&gt;
=== unit ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''unit''' &amp;amp;larr; ''unit or unit type''&lt;br /&gt;
* Available on: '''[unit_preview_pane]'''&lt;br /&gt;
&lt;br /&gt;
Change the displayed unit or unit type in the preview pane.&lt;br /&gt;
&lt;br /&gt;
=== item_count ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''item_count''' &amp;amp;rarr; ''number of items''&lt;br /&gt;
* Available on: '''[multi_page]''', '''[listbox]'''&lt;br /&gt;
&lt;br /&gt;
The number of items in the container widget.&lt;br /&gt;
&lt;br /&gt;
=== use_markup ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''use_markup''' &amp;amp;rarr; ''boolean''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Sets whether the widget's label will parse [[Pango formatting]].&lt;br /&gt;
&lt;br /&gt;
=== label ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''label''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]''', '''[image]'''&lt;br /&gt;
&lt;br /&gt;
The widget's label. Technically this is a special string used in the widget's wml definition. It usually does what one would expect, but also sets the image for '''image''' widgets.  For '''[text_box]''', use '''text''' for initial values.&lt;br /&gt;
&lt;br /&gt;
=== marked_up_text ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''marked_up_text''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: Most widgets, in particular '''[label]''', '''[button]'''&lt;br /&gt;
&lt;br /&gt;
Shortcut for setting label and use_markup=yes.&lt;br /&gt;
&lt;br /&gt;
=== enabled ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''enabled''' &amp;amp;larr; ''boolean''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
=== tooltip ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''tooltip''' &amp;amp;larr; ''text''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
=== visible ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''visible''' &amp;amp;larr; ''visibility string''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Determines whether the widget is visible onscreen. The following visibility statuses are recognized:&lt;br /&gt;
{| clasS=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! String value !! Boolean shorthand !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| visible || true || The widget is visible and handles events.&lt;br /&gt;
|-&lt;br /&gt;
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.&lt;br /&gt;
|-&lt;br /&gt;
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''type''' &amp;amp;rarr; ''string''&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Returns a string specifying the type of the widget.&lt;br /&gt;
&lt;br /&gt;
== Widget callbacks ==&lt;br /&gt;
&lt;br /&gt;
=== on_modified ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_modified''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: Most widgets, in particular '''[slider]''', '''[toggle_button]''', '''[listbox]''', '''[menu_button]''', '''[text_box]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user changes the value of the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_left_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_left_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: All widgets&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the widget.&lt;br /&gt;
&lt;br /&gt;
=== on_button_click ===&lt;br /&gt;
&lt;br /&gt;
* ''widget''.'''on_button_click''' &amp;amp;larr; '''function'''()&lt;br /&gt;
* Available on: '''[button]''', '''[repeating_button]'''&lt;br /&gt;
&lt;br /&gt;
Triggers when the user clicks on the button. This can differ from '''on_left_click''', depending on the type of widget. For example, on a '''[repeating_button]''' it will fire multiple times if the user holds the mouse button down.&lt;br /&gt;
&lt;br /&gt;
== Widget methods ==&lt;br /&gt;
&lt;br /&gt;
Any function defined in the [[LuaAPI/gui/widget|gui.widget]] module and taking a widget as its first parameter can be called as a method of a widget. This includes any functions that are added to the module by user code. Note that these methods are available even if the widget itself doesn't support that function, so in some cases it may be necessary to check '''widget.type''' befor calling the method.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73901</id>
		<title>GUIWidgetInstanceWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73901"/>
		<updated>2024-10-25T18:05:19Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Multiline Text */  - use scroll_text in GUIs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Widget instance ==&lt;br /&gt;
Inside a grid (which is inside all container widgets) a widget is&lt;br /&gt;
instantiated. With this instantiation some more variables of a widget can&lt;br /&gt;
be tuned. This page will describe what can be tuned.&lt;br /&gt;
&lt;br /&gt;
== Widget ==&lt;br /&gt;
All widgets placed in the cell have some values in common:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| This value is used for the engine to identify 'special' items. This means that for example a text_box can get the proper initial value. This value should be unique or empty. Those special values are documented at the window definition that uses them. NOTE items starting with an underscore are used for composed widgets and these should be unique per composed widget.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;default&amp;quot;&lt;br /&gt;
| The id of the widget definition to use. This way it's possible to select a specific version of the widget e.g. a title label when the label is used as title.&lt;br /&gt;
|-&lt;br /&gt;
| linked_group&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The linked group the control belongs to.&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Most widgets have some text associated with them, this field contain the value of that text. Some widgets use this value for other purposes, this is documented at the widget. E.g. an image uses the filename in this field.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget a while (the time it takes can differ per widget) a short help can show up.This defines the text of that message. This field may not be empty when 'help' is set.&lt;br /&gt;
|-&lt;br /&gt;
| help&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget and press F10 (or the key the user defined for the help tip) a help message can show up. This help message might be the same as the tooltip but in general (if used) this message should show more help. This defines the text of that message.&lt;br /&gt;
|-&lt;br /&gt;
| use_tooltip_on_label_overflow&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If the text on the label is truncated and the tooltip is empty the label can be used for the tooltip. If this variable is set to true this will happen.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_mode&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The mode for showing the debug border. This border shows the area reserved for a widget. This function is only meant for debugging and might not be available in all Wesnoth binaries. Available modes: &lt;br /&gt;
* '''0:''' no border. &lt;br /&gt;
* '''1:''' 1 pixel border. &lt;br /&gt;
* '''2:''' floodfill the widget area.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the debug border.&lt;br /&gt;
|-&lt;br /&gt;
| size_text&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Sets the minimum width of the widget depending on the text in it. (Note not implemented yet.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Button ==&lt;br /&gt;
A button is a control that can be pushed to start an action or close a dialog.&lt;br /&gt;
&lt;br /&gt;
Instance of a button. When a button has a return value it sets the&lt;br /&gt;
return value for the window. Normally this closes the window and returns&lt;br /&gt;
this value to the caller. The return value can either be defined by the&lt;br /&gt;
user or determined from the id of the button. The return value has a&lt;br /&gt;
higher precedence as the one defined by the id. (Of course it's weird to&lt;br /&gt;
give a button an id and then override its return value.)&lt;br /&gt;
&lt;br /&gt;
When the button doesn't have a standard id, but you still want to use the&lt;br /&gt;
return value of that id, use return_value_id instead. This has a higher&lt;br /&gt;
precedence as return_value.&lt;br /&gt;
&lt;br /&gt;
List with the button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Supported values for return_value_id:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!string&lt;br /&gt;
!value&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;ok&amp;quot;||-1||Equivalent to closing the dialog by pressing the Enter key&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;cancel&amp;quot;||-2||Equivalent to closing the dialog by pressing the Esc key&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;quit&amp;quot;||-2||An alias for cancel&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;&amp;quot;||N/A||Clears any previously set return_value_id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Combobox ==&lt;br /&gt;
[[File:Combobox.png|frame|right|A Combobox with its list open]]&lt;br /&gt;
A widget with a text box and a dropdown list. Selecting an element from the list sets the value of the text box to that item of the list. The user can also manually enter a value in the text box.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! key !! type !! default !! description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The text of the combobox&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;combobox&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Drawing ==&lt;br /&gt;
A drawing is widget with a fixed size and gives access to the canvas of the widget in the window instance. This allows special display only widgets.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is not zero the drawing functions as a&lt;br /&gt;
fixed size drawing.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| draw&lt;br /&gt;
| [[GUIVariable#config|config]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The config containing the drawing.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Grid Listbox ==&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Horizontal listbox ==&lt;br /&gt;
A horizontal listbox is a control that holds several items of the same type.  Normally the items in a listbox are ordered in rows, this version orders them in columns instead.&lt;br /&gt;
&lt;br /&gt;
List with the horizontal listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a horizontal listbox,&lt;br /&gt;
the widgets need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
An image shows a static image whose path is specified by its '''[[GUIWidgetInstanceWML#Widget|label]]''' key. Unlike other widgets, the '''label''' key here is not translatable since it specifies a path. The path is a standard WML path, i.e., &amp;lt;code&amp;gt;label=&amp;quot;units/konrad.png&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;label=&amp;quot;~add-ons/MyAddon/image/test.png&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It has no other extra fields.&lt;br /&gt;
&lt;br /&gt;
== Label ==&lt;br /&gt;
A label displays text provided via the '''[[GUIWidgetInstanceWML#Widget|label]]''' key that can be wrapped but no scrollbars are provided. For a version with scrollbars, see the [[GUIWidgetInstanceWML#Scroll_Label|Scroll Label]] widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Title Label.png|frame|right|A Label with definition &amp;quot;title&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
List with the label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| wrap || [[GUIVariable#bool|bool]] || false || Is wrapping enabled for the label.&lt;br /&gt;
|-&lt;br /&gt;
| characters_per_line || [[GUIVariable#unsigned|unsigned]] || 0 || Sets the maximum number of characters per line. The amount is an approximate since the width of a character differs. E.g. iii is smaller than MMM. When the value is non-zero it also implies '''can_wrap''' is true. &lt;br /&gt;
When having long strings, wrapping them can increase readability. A rule of thumb is 66 characters per line is considered the optimum for a one column text.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| can_shrink || [[GUIVariable#bool|bool]] || false || Whether the label can shrink past its optimal size.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Listbox ==&lt;br /&gt;
A listbox is a control that holds several items of the same type. Normally the items in a listbox are ordered in rows, this version might allow more options for ordering the items in the future.&lt;br /&gt;
&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a listbox, the widgets&lt;br /&gt;
need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Matrix ==&lt;br /&gt;
List with the matrix specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Menu Button ==&lt;br /&gt;
[[File:Menu Button.png|thumb|left|A Menu Button with it's list open.]]&lt;br /&gt;
A button that shows a dropdown list when clicked. The user can select any one of the predefined options.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;menu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Minimap ==&lt;br /&gt;
A minimap to show the gamemap, this only shows the map and has no interaction options. This version is used for map previews, there will be a another version which allows interaction.&lt;br /&gt;
&lt;br /&gt;
A minimap has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Multiline Text ==&lt;br /&gt;
Base class for a multiline text area.  Not to be used directly in a GUI, use the [[GUIWidgetInstanceWML#Scroll_Text|scroll_text]] widget instead.&lt;br /&gt;
&lt;br /&gt;
The following variables exist:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multimenu Button ==&lt;br /&gt;
[[File:Multimenu Button.png|thumb|right|A Multimenu Button with its list open]]&lt;br /&gt;
A widget clicking on which shows a list from which one or more options can be selected.&lt;br /&gt;
&lt;br /&gt;
List with the multimenu_button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value || [[GUIVariable#int|int]] || 0 || The return value.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_shown || [[GUIVariable#int|int]] || -1 || The maximum number of currently selected values to list on the button.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;multimenu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| checkbox || [[GUIVariable#bool|bool]] || &amp;quot;&amp;quot; || Whether the checkbox alongside this option is selected or not.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multi page ==&lt;br /&gt;
A multi page is a control that contains several 'pages' of which only one is visible. The pages can contain the same widgets containing the same 'kind' of data or look completely different.&lt;br /&gt;
&lt;br /&gt;
List with the multi page specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| page_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a multi page item looks. It must contain the grid definition for at least one page.&lt;br /&gt;
|-&lt;br /&gt;
| page_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the multi page. Every row must have the same number of columns as the 'page_definition'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Panel ==&lt;br /&gt;
A panel is an item which can hold other items. The difference between a grid and a panel is that it's possible to define how a panel looks. A grid in an invisible container to just hold the items.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Password box ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the password box.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Progress bar ==&lt;br /&gt;
A progress bar shows the progress of a certain object.&lt;br /&gt;
&lt;br /&gt;
A progress bar has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Repeating button ==&lt;br /&gt;
A repeating_button is a control that can be pushed down and repeat a certain action. Once the button is down every x milliseconds it is down a new down event is triggered.&lt;br /&gt;
&lt;br /&gt;
== Rich Label ==&lt;br /&gt;
A label that shows formatted text marked up with [[Help markup]]. It can show embedded images, links and tables inside text.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#int|int]] || 500 || Width of its internal formatted content. Text will wrap beyond this width.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll label ==&lt;br /&gt;
A scroll label is a label that wraps its text and also has a vertical scrollbar. This way a text can't be too long to be shown for this widget.&lt;br /&gt;
&lt;br /&gt;
List with the scroll label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scrollbar panel ==&lt;br /&gt;
Instance of a scrollbar_panel.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar_panel specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a scrollbar_panel item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Spacer ==&lt;br /&gt;
A spacer is a dummy item to either fill in a widget since no empty items are allowed or to reserve a fixed space.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is non-zero the spacer functions as a&lt;br /&gt;
fixed size spacer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The width of the spacer.&lt;br /&gt;
|-&lt;br /&gt;
| height || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The height of the spacer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Tab Container ==&lt;br /&gt;
&lt;br /&gt;
A container widget that can show its contents separated into various pages, each of which are accessible.&lt;br /&gt;
&lt;br /&gt;
It can contain one or more &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tags inside it, each defining a tab's name, image (if any) and the contents of the tag, specified by the &amp;lt;code&amp;gt;[data]&amp;lt;/code&amp;gt; tag inside the &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
=== Subtag [tab] ===&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| name || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the tab&lt;br /&gt;
|-&lt;br /&gt;
| image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image for the tab to be shown alongside the name, if any&lt;br /&gt;
|-&lt;br /&gt;
| [data] || [[GUIVariable#grid|grid]] || empty grid || This subtag contains a grid that defines the contents for this tab.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text box ==&lt;br /&gt;
A single line text entry widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Text Box.png|frame|right|A Text Box]]&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| editable || [[GUIVariable#bool|bool]] || &amp;quot;true&amp;quot; || If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle panel ==&lt;br /&gt;
A toggle panel is an item which can hold other items. The difference between&lt;br /&gt;
a grid and a panel is that it's possible to define how a panel looks. A grid&lt;br /&gt;
in an invisible container to just hold the items. The toggle panel is a&lt;br /&gt;
combination of the panel and a toggle button, it allows a toggle button with&lt;br /&gt;
its own grid.&lt;br /&gt;
&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Tree view ==&lt;br /&gt;
A tree view is a control that holds several items of the same or different types. The items shown are called tree view nodes and when a node has children, these can be shown or hidden. Nodes that contain children need to provide a clickable button in order to fold or unfold the children.&lt;br /&gt;
&lt;br /&gt;
List with the tree view specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| indention_step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of pixels every level of nodes is indented from the previous level.&lt;br /&gt;
|-&lt;br /&gt;
| node&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The tree view can contain multiple node sections. This part needs more documentation.&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE more documentation and examples are needed.&lt;br /&gt;
&lt;br /&gt;
== Vertical scrollbar ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Viewport ==&lt;br /&gt;
A viewport is an special widget used to view only a part of the widget it `holds'.&lt;br /&gt;
&lt;br /&gt;
List with the viewport specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grow_direction&lt;br /&gt;
| [[GUIVariable#grow_direction|grow_direction]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The direction in which new items grow.&lt;br /&gt;
|-&lt;br /&gt;
| parallel_items&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The number of items that are growing in parallel.&lt;br /&gt;
|-&lt;br /&gt;
| item_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The definition of a new item.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll Text ==&lt;br /&gt;
A multiline text area that shows a scrollbar if the text gets too long.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar container specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of this scroll_text can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slider ==&lt;br /&gt;
&lt;br /&gt;
A slider is a control that can select a value by moving a grip on a groove.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| best_slider_length&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The best length for the sliding part.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The minimum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The maximum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of items the slider's value increases with one step.&lt;br /&gt;
|-&lt;br /&gt;
| value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The value of the slider.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the minimum value is chosen there might be the need for a special value (eg off). When this key has a value that value will be shown if the minimum is selected.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the maximum value is chosen there might be the need for a special value (eg unlimited)). When this key has a value that value will be shown if the maximum is selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle button ==&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Talk:GUIWidgetDefinitionWML&amp;diff=73898</id>
		<title>Talk:GUIWidgetDefinitionWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Talk:GUIWidgetDefinitionWML&amp;diff=73898"/>
		<updated>2024-10-24T15:07:47Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: Created page with &amp;quot;There are two sections for Scrollbar Panel.  It's not clear to me why. ~~~~&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are two sections for Scrollbar Panel.  It's not clear to me why.&lt;br /&gt;
[[User:White haired uncle|White haired uncle]] ([[User talk:White haired uncle|talk]]) 15:07, 24 October 2024 (UTC)&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/gui/widget&amp;diff=73892</id>
		<title>LuaAPI/gui/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/gui/widget&amp;diff=73892"/>
		<updated>2024-10-21T21:04:55Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: Add clear()&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
The '''gui.widget''' module contains functions for managing widgets in custom GUI2 dialogs. Since these functions take a [[LuaAPI/types/widget|widget userdata]] as the first parameter, they can only be used in the preshow or postshow of a GUI2 dialog (directly or indirectly). However, the table is available at all times, and additional methods can be installed here for unusual needs.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The '''gui.widget.set_callback''' is a compatibility wrapper and is unsupported. It may be removed without warning. Callbacks should be bound by assigning the appropriate callback key on the widget.&lt;br /&gt;
&lt;br /&gt;
=== focus ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.focus'''(''widget'')&lt;br /&gt;
* ''widget'':'''focus'''()&lt;br /&gt;
&lt;br /&gt;
Switches the keyboard focus to the widget. This is often useful for dialogs containing a central listbox, so that it can be controlled with the keyboard as soon as it is displayed.&lt;br /&gt;
&lt;br /&gt;
=== set_canvas ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.set_canvas'''(''widget'', ''layer index'', ''content'')&lt;br /&gt;
* ''widget'':'''set_canvas'''(''layer index'', ''content'')&lt;br /&gt;
&lt;br /&gt;
Sets the WML passed as the second argument as the canvas content (index given by the first argument) of the widget. The content of the WML table depends on which shape is used:&lt;br /&gt;
&lt;br /&gt;
* [[GUICanvasWML#Circle|Circle]]&lt;br /&gt;
* [[GUICanvasWML#Image|Image]]&lt;br /&gt;
* [[GUICanvasWML#Line|Line]]&lt;br /&gt;
* [[GUICanvasWML#Bounded_Shape|common attributes of rectangles, round rectangles and text]]&lt;br /&gt;
* [[GUICanvasWML#Rectangle|Rectangle]]&lt;br /&gt;
* [[GUICanvasWML#Rounded_Rectangle|Rounded Rectangle]]&lt;br /&gt;
* [[GUICanvasWML#Text|Text]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
-- draw two rectangles in the upper-left corner of the window (assume dialog is the window widget)&lt;br /&gt;
dialog:set_canvas(2, {&lt;br /&gt;
    wml.tag.rectangle { x = 20, y = 20, w = 20, h = 20, fill_color= &amp;quot;0,0,255,255&amp;quot; },&lt;br /&gt;
    wml.tag.rectangle { x = 30, y = 30, w = 20, h = 20, fill_color = &amp;quot;255,0,0,255&amp;quot; }&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the canvas index depends on the chosen widget. It may be the disabled / enabled states of the widget, or its background / foreground planes, or... For instance, overwriting canvas 1 of the window with an empty canvas causes the window to become transparent.&lt;br /&gt;
&lt;br /&gt;
=== add_item ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.add_item'''(''widget'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
* ''widget'':'''add_item'''([''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
&lt;br /&gt;
Add an item to a container widget, for example a listbox. Returns the created item as a [[LuaAPI/types/widget|widget userdata]].&lt;br /&gt;
&lt;br /&gt;
=== add_item_of_type ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.add_item_of_type'''(''widget'', ''category'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
* ''widget'':'''add_item_of_type'''(''category'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
&lt;br /&gt;
Add an item to a widget which is a heterogeneous container of different types of widgets, in particular multi_pages and treeviews.&lt;br /&gt;
&lt;br /&gt;
=== remove_items_at ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.remove_items_at'''(''widget'', ''position'', ''count'')&lt;br /&gt;
* ''widget'':'''remove_items_at'''(''position'', ''count'')&lt;br /&gt;
&lt;br /&gt;
Removes one or more elements of a container type widget (like treeviews), starting at the given index. If 0 is passed as the count, all elements from that point to the end are removed. Otherwise, the specified number of elements are removed.&lt;br /&gt;
&lt;br /&gt;
=== clear ===&lt;br /&gt;
{{DevFeature1.19|5}}&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.clear'''(''widget'')&lt;br /&gt;
* ''widget'':'''clear'''()&lt;br /&gt;
&lt;br /&gt;
Removes all elements of a container type widget. &lt;br /&gt;
&lt;br /&gt;
=== find ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.find'''(''root widget'', ...)&lt;br /&gt;
* ''widget'':'''find'''(...)&lt;br /&gt;
&lt;br /&gt;
Finds a child widget of the widget of the given path. For example, here it searches for the widget with the id 'preview_panel' of the second item of the widget with the id 'unit_list':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog:find('unit_list', 2, 'preview_panel')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is more or less equivalent to the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.unit_list[2].preview_panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, if the path comes from a variable, the functional form may be more convenient:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog:find(table.unpack(path))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== close ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.close'''(''dialog'')&lt;br /&gt;
* ''widget'':'''close'''()&lt;br /&gt;
&lt;br /&gt;
Closes the dialog.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73823</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73823"/>
		<updated>2024-09-29T16:06:39Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Listbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.  The third item has been selected.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73822</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73822"/>
		<updated>2024-09-29T16:05:55Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Listbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
&lt;br /&gt;
Note that listbox items are added from top to bottom.  Another container, the horizontal_listbox, works just like a listbox except the items are added from left to right.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items.  Each item is an image and a label.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Talk:GUIToolkitWML&amp;diff=73818</id>
		<title>Talk:GUIToolkitWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Talk:GUIToolkitWML&amp;diff=73818"/>
		<updated>2024-09-26T14:03:30Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Feedback */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Feedback ==&lt;br /&gt;
&lt;br /&gt;
There are two Resolution sections, mostly redundant (ah, I see now, widget vs window, confusing at first)&lt;br /&gt;
&lt;br /&gt;
popup_* - might want to mention the word &amp;quot;tooltip&amp;quot; in there - I assume that's what a &amp;quot;popup&amp;quot; is&lt;br /&gt;
&lt;br /&gt;
Settings &amp;gt; has_helptip_message - &amp;quot;The string used to append the tooltip &amp;quot; should that be &amp;quot;The string used to append to the tooltip&amp;quot; (assuming that's how it works)? &lt;br /&gt;
&lt;br /&gt;
&amp;quot;A linked group needs to have at least one size fixed. &amp;quot; - one fixed size?&lt;br /&gt;
: No, that's correct. It means either the width or height needs to be fixed. [[User:Celtic Minstrel|Celtic Minstrel]] ([[User talk:Celtic Minstrel|talk]]) 13:59, 26 September 2024 (UTC)&lt;br /&gt;
&lt;br /&gt;
Toggle Button:&lt;br /&gt;
&lt;br /&gt;
# GUIToolkitWML#Button is a link that doesn't seem to go anywhere (yet?)&lt;br /&gt;
# &amp;quot;List if the id's that have generate a return value:&amp;quot; - this looks like a list of the valid values of return_value_id. I have no idea what that phrase means as written.  Also, quit (an alias for cancel) is missing&lt;br /&gt;
 &lt;br /&gt;
[[User:White haired uncle|White haired uncle]] ([[User talk:White haired uncle|talk]]) 14:03, 26 September 2024 (UTC)&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73810</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73810"/>
		<updated>2024-09-25T20:29:48Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Slider and Textbox */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function slider_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Talk:GUIToolkitWML&amp;diff=73809</id>
		<title>Talk:GUIToolkitWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Talk:GUIToolkitWML&amp;diff=73809"/>
		<updated>2024-09-25T10:53:00Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Feedback */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Feedback ==&lt;br /&gt;
&lt;br /&gt;
There are two Resolution sections, mostly redundant&lt;br /&gt;
&lt;br /&gt;
popup_* - might want to mention the word &amp;quot;tooltip&amp;quot; in there - I assume that's what a &amp;quot;popup&amp;quot; is&lt;br /&gt;
&lt;br /&gt;
Settings &amp;gt; has_helptip_message - &amp;quot;The string used to append the tooltip &amp;quot; should that be &amp;quot;The string used to append to the tooltip&amp;quot; (assuming that's how it works)? &lt;br /&gt;
&lt;br /&gt;
&amp;quot;A linked group needs to have at least one size fixed. &amp;quot; - one fixed size?&lt;br /&gt;
&lt;br /&gt;
Toggle Button:&lt;br /&gt;
&lt;br /&gt;
# GUIToolkitWML#Button is a link that doesn't seem to go anywhere (yet?)&lt;br /&gt;
# &amp;quot;List if the id's that have generate a return value:&amp;quot; - this looks like a list of the valid values of return_value_id. I have no idea what that phrase means as written.  Also, quit (an alias for cancel) is missing&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Talk:GUIToolkitWML&amp;diff=73808</id>
		<title>Talk:GUIToolkitWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Talk:GUIToolkitWML&amp;diff=73808"/>
		<updated>2024-09-25T10:51:27Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Feedback */ new section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Feedback ==&lt;br /&gt;
&lt;br /&gt;
There are two Resolution sections, mostly redundant&lt;br /&gt;
&lt;br /&gt;
popup_* - might want to mention the word &amp;quot;tooltip&amp;quot; in there - I assume that's what a &amp;quot;popup&amp;quot; is&lt;br /&gt;
&lt;br /&gt;
Settings &amp;gt; has_helptip_message - &amp;quot;The string used to append the tooltip &amp;quot; should that be &amp;quot;The string used to append to the tooltip&amp;quot; (assuming that's how it works)? &lt;br /&gt;
&lt;br /&gt;
&amp;quot;A linked group needs to have at least one size fixed. &amp;quot; - one fixed size?&lt;br /&gt;
&lt;br /&gt;
Toggle Button:&lt;br /&gt;
&lt;br /&gt;
1) GUIToolkitWML#Button is a link that doesn't seem to go anywhere (yet?)&lt;br /&gt;
2) &amp;quot;List if the id's that have generate a return value:&amp;quot; - this looks like a list of the valid values of return_value_id. I have no idea what that phrase means as written.&lt;br /&gt;
   quit (an alias for cancel) is missing&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73807</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73807"/>
		<updated>2024-09-25T10:50:40Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Useful Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML]] - Documents the keys/values available on various objects (e.g. &amp;quot;what attributes can I set on a column?&amp;quot;) &amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui]] - Mostly about opening windows&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget]] - Widget attributes and callbacks&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73806</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73806"/>
		<updated>2024-09-25T10:48:15Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Appendix */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
[[GUIToolkitWML - Documents the keys/values available on various objects (&amp;quot;what attributes can I set on a column?&amp;quot;]] &lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui - Mostly about opening windows]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget|LuaAPI/types/widget - Widget attributes and callbacks]]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73805</id>
		<title>GUIWidgetInstanceWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73805"/>
		<updated>2024-09-24T18:47:52Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Button - add description of valid values for return_value_id */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Widget instance ==&lt;br /&gt;
Inside a grid (which is inside all container widgets) a widget is&lt;br /&gt;
instantiated. With this instantiation some more variables of a widget can&lt;br /&gt;
be tuned. This page will describe what can be tuned.&lt;br /&gt;
&lt;br /&gt;
== Widget ==&lt;br /&gt;
All widgets placed in the cell have some values in common:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| This value is used for the engine to identify 'special' items. This means that for example a text_box can get the proper initial value. This value should be unique or empty. Those special values are documented at the window definition that uses them. NOTE items starting with an underscore are used for composed widgets and these should be unique per composed widget.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;default&amp;quot;&lt;br /&gt;
| The id of the widget definition to use. This way it's possible to select a specific version of the widget e.g. a title label when the label is used as title.&lt;br /&gt;
|-&lt;br /&gt;
| linked_group&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The linked group the control belongs to.&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Most widgets have some text associated with them, this field contain the value of that text. Some widgets use this value for other purposes, this is documented at the widget. E.g. an image uses the filename in this field.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget a while (the time it takes can differ per widget) a short help can show up.This defines the text of that message. This field may not be empty when 'help' is set.&lt;br /&gt;
|-&lt;br /&gt;
| help&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget and press F10 (or the key the user defined for the help tip) a help message can show up. This help message might be the same as the tooltip but in general (if used) this message should show more help. This defines the text of that message.&lt;br /&gt;
|-&lt;br /&gt;
| use_tooltip_on_label_overflow&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If the text on the label is truncated and the tooltip is empty the label can be used for the tooltip. If this variable is set to true this will happen.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_mode&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The mode for showing the debug border. This border shows the area reserved for a widget. This function is only meant for debugging and might not be available in all Wesnoth binaries. Available modes: &lt;br /&gt;
* 0 no border. &lt;br /&gt;
* 1 1 pixel border. &lt;br /&gt;
* 2 floodfill the widget area.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the debug border.&lt;br /&gt;
|-&lt;br /&gt;
| size_text&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Sets the minimum width of the widget depending on the text in it. (Note not implemented yet.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Button ==&lt;br /&gt;
A button is a control that can be pushed to start an action or close a dialog.&lt;br /&gt;
&lt;br /&gt;
Instance of a button. When a button has a return value it sets the&lt;br /&gt;
return value for the window. Normally this closes the window and returns&lt;br /&gt;
this value to the caller. The return value can either be defined by the&lt;br /&gt;
user or determined from the id of the button. The return value has a&lt;br /&gt;
higher precedence as the one defined by the id. (Of course it's weird to&lt;br /&gt;
give a button an id and then override its return value.)&lt;br /&gt;
&lt;br /&gt;
When the button doesn't have a standard id, but you still want to use the&lt;br /&gt;
return value of that id, use return_value_id instead. This has a higher&lt;br /&gt;
precedence as return_value.&lt;br /&gt;
&lt;br /&gt;
List with the button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Supported values for return_value_id:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!string&lt;br /&gt;
!value&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;ok&amp;quot;||-1||Equivalent to closing the dialog by pressing the Enter key&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;cancel&amp;quot;||-2||Equivalent to closing the dialog by pressing the Esc key&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;quit&amp;quot;||-2||An alias for cancel&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;&amp;quot;||N/A||Clears any previously set return_value_id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Combobox ==&lt;br /&gt;
[[File:Combobox.png|frame|right|A Combobox with its list open]]&lt;br /&gt;
A widget with a text box and a dropdown list. Selecting an element from the list sets the value of the text box to that item of the list. The user can also manually enter a value in the text box.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! key !! type !! default !! description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The text of the combobox&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;combobox&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Drawing ==&lt;br /&gt;
A drawing is widget with a fixed size and gives access to the canvas of the widget in the window instance. This allows special display only widgets.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is not zero the drawing functions as a&lt;br /&gt;
fixed size drawing.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| draw&lt;br /&gt;
| [[GUIVariable#config|config]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The config containing the drawing.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Grid Listbox ==&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Horizontal listbox ==&lt;br /&gt;
A horizontal listbox is a control that holds several items of the same type.  Normally the items in a listbox are ordered in rows, this version orders them in columns instead.&lt;br /&gt;
&lt;br /&gt;
List with the horizontal listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a horizontal listbox,&lt;br /&gt;
the widgets need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
An image shows a static image.&lt;br /&gt;
&lt;br /&gt;
An image has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Label ==&lt;br /&gt;
A label displays text that can be wrapped but no scrollbars are provided.&lt;br /&gt;
&lt;br /&gt;
[[File:Title Label.png|frame|right|A Label with definition &amp;quot;title&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
List with the label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| wrap || [[GUIVariable#bool|bool]] || false || Is wrapping enabled for the label.&lt;br /&gt;
|-&lt;br /&gt;
| characters_per_line || [[GUIVariable#unsigned|unsigned]] || 0 || Sets the maximum number of characters per line. The amount is an approximate since the width of a character differs. E.g. iii is smaller than MMM. When the value is non-zero it also implies can_wrap is true. When having long strings wrapping them can increase readability, often 66 characters per line is considered the optimum for a one column text. text_alignment &amp;amp; h_align &amp;amp; &amp;quot;left&amp;quot; &amp;amp; How is the text aligned in the label.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| can_shrink || [[GUIVariable#bool|bool]] || false || Whether the label can shrink past its optimal size.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Listbox ==&lt;br /&gt;
A listbox is a control that holds several items of the same type. Normally the items in a listbox are ordered in rows, this version might allow more options for ordering the items in the future.&lt;br /&gt;
&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a listbox, the widgets&lt;br /&gt;
need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Matrix ==&lt;br /&gt;
List with the matrix specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Menu Button ==&lt;br /&gt;
[[File:Menu Button.png|thumb|left|A Menu Button with it's list open.]]&lt;br /&gt;
A button that shows a dropdown list when clicked. The user can select any one of the predefined options.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;menu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Minimap ==&lt;br /&gt;
A minimap to show the gamemap, this only shows the map and has no interaction options. This version is used for map previews, there will be a another version which allows interaction.&lt;br /&gt;
&lt;br /&gt;
A minimap has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Multiline Text ==&lt;br /&gt;
Base class for a multiline text area.&lt;br /&gt;
&lt;br /&gt;
The following variables exist:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multimenu Button ==&lt;br /&gt;
[[File:Multimenu Button.png|thumb|right|A Multimenu Button with its list open]]&lt;br /&gt;
A widget clicking on which shows a list from which one or more options can be selected.&lt;br /&gt;
&lt;br /&gt;
List with the multimenu_button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value || [[GUIVariable#int|int]] || 0 || The return value.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_shown || [[GUIVariable#int|int]] || -1 || The maximum number of currently selected values to list on the button.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;multimenu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| checkbox || [[GUIVariable#bool|bool]] || &amp;quot;&amp;quot; || Whether the checkbox alongside this option is selected or not.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multi page ==&lt;br /&gt;
A multi page is a control that contains several 'pages' of which only one is visible. The pages can contain the same widgets containing the same 'kind' of data or look completely different.&lt;br /&gt;
&lt;br /&gt;
List with the multi page specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| page_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a multi page item looks. It must contain the grid definition for at least one page.&lt;br /&gt;
|-&lt;br /&gt;
| page_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the multi page. Every row must have the same number of columns as the 'page_definition'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Panel ==&lt;br /&gt;
A panel is an item which can hold other items. The difference between a grid and a panel is that it's possible to define how a panel looks. A grid in an invisible container to just hold the items.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Password box ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the password box.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Progress bar ==&lt;br /&gt;
A progress bar shows the progress of a certain object.&lt;br /&gt;
&lt;br /&gt;
A progress bar has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Repeating button ==&lt;br /&gt;
A repeating_button is a control that can be pushed down and repeat a certain action. Once the button is down every x milliseconds it is down a new down event is triggered.&lt;br /&gt;
&lt;br /&gt;
== Rich Label ==&lt;br /&gt;
A label that shows formatted text marked up with [[Help markup]]. It can show embedded images, links and tables inside text.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#int|int]] || 500 || Width of its internal formatted content. Text will wrap beyond this width.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll label ==&lt;br /&gt;
A scroll label is a label that wraps its text and also has a vertical scrollbar. This way a text can't be too long to be shown for this widget.&lt;br /&gt;
&lt;br /&gt;
List with the scroll label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scrollbar panel ==&lt;br /&gt;
Instance of a scrollbar_panel.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar_panel specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a scrollbar_panel item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Spacer ==&lt;br /&gt;
A spacer is a dummy item to either fill in a widget since no empty items are allowed or to reserve a fixed space.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is non-zero the spacer functions as a&lt;br /&gt;
fixed size spacer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The width of the spacer.&lt;br /&gt;
|-&lt;br /&gt;
| height || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The height of the spacer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Tab Container ==&lt;br /&gt;
&lt;br /&gt;
A container widget that can show its contents separated into various pages, each of which are accessible.&lt;br /&gt;
&lt;br /&gt;
It can contain one or more &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tags inside it, each defining a tab's name, image (if any) and the contents of the tag, specified by the &amp;lt;code&amp;gt;[data]&amp;lt;/code&amp;gt; tag inside the &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
=== Subtag [tab] ===&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| name || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the tab&lt;br /&gt;
|-&lt;br /&gt;
| image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image for the tab to be shown alongside the name, if any&lt;br /&gt;
|-&lt;br /&gt;
| [data] || [[GUIVariable#grid|grid]] || empty grid || This subtag contains a grid that defines the contents for this tab.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text box ==&lt;br /&gt;
A single line text entry widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Text Box.png|frame|right|A Text Box]]&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| editable || [[GUIVariable#bool|bool]] || &amp;quot;true&amp;quot; || If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle panel ==&lt;br /&gt;
A toggle panel is an item which can hold other items. The difference between&lt;br /&gt;
a grid and a panel is that it's possible to define how a panel looks. A grid&lt;br /&gt;
in an invisible container to just hold the items. The toggle panel is a&lt;br /&gt;
combination of the panel and a toggle button, it allows a toggle button with&lt;br /&gt;
its own grid.&lt;br /&gt;
&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Tree view ==&lt;br /&gt;
A tree view is a control that holds several items of the same or different types. The items shown are called tree view nodes and when a node has children, these can be shown or hidden. Nodes that contain children need to provide a clickable button in order to fold or unfold the children.&lt;br /&gt;
&lt;br /&gt;
List with the tree view specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| indention_step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of pixels every level of nodes is indented from the previous level.&lt;br /&gt;
|-&lt;br /&gt;
| node&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The tree view can contain multiple node sections. This part needs more documentation.&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE more documentation and examples are needed.&lt;br /&gt;
&lt;br /&gt;
== Vertical scrollbar ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Viewport ==&lt;br /&gt;
A viewport is an special widget used to view only a part of the widget it `holds'.&lt;br /&gt;
&lt;br /&gt;
List with the viewport specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grow_direction&lt;br /&gt;
| [[GUIVariable#grow_direction|grow_direction]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The direction in which new items grow.&lt;br /&gt;
|-&lt;br /&gt;
| parallel_items&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The number of items that are growing in parallel.&lt;br /&gt;
|-&lt;br /&gt;
| item_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The definition of a new item.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll Text ==&lt;br /&gt;
A multiline text area that shows a scrollbar if the text gets too long.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar container specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of this scroll_text can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slider ==&lt;br /&gt;
&lt;br /&gt;
A slider is a control that can select a value by moving a grip on a groove.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| best_slider_length&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The best length for the sliding part.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The minimum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The maximum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of items the slider's value increases with one step.&lt;br /&gt;
|-&lt;br /&gt;
| value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The value of the slider.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the minimum value is chosen there might be the need for a special value (eg off). When this key has a value that value will be shown if the minimum is selected.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the maximum value is chosen there might be the need for a special value (eg unlimited)). When this key has a value that value will be shown if the maximum is selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle button ==&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73804</id>
		<title>GUIWidgetInstanceWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73804"/>
		<updated>2024-09-24T18:45:24Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Button */  add description of valid values for return_value_id&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Widget instance ==&lt;br /&gt;
Inside a grid (which is inside all container widgets) a widget is&lt;br /&gt;
instantiated. With this instantiation some more variables of a widget can&lt;br /&gt;
be tuned. This page will describe what can be tuned.&lt;br /&gt;
&lt;br /&gt;
== Widget ==&lt;br /&gt;
All widgets placed in the cell have some values in common:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| This value is used for the engine to identify 'special' items. This means that for example a text_box can get the proper initial value. This value should be unique or empty. Those special values are documented at the window definition that uses them. NOTE items starting with an underscore are used for composed widgets and these should be unique per composed widget.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;default&amp;quot;&lt;br /&gt;
| The id of the widget definition to use. This way it's possible to select a specific version of the widget e.g. a title label when the label is used as title.&lt;br /&gt;
|-&lt;br /&gt;
| linked_group&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The linked group the control belongs to.&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Most widgets have some text associated with them, this field contain the value of that text. Some widgets use this value for other purposes, this is documented at the widget. E.g. an image uses the filename in this field.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget a while (the time it takes can differ per widget) a short help can show up.This defines the text of that message. This field may not be empty when 'help' is set.&lt;br /&gt;
|-&lt;br /&gt;
| help&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget and press F10 (or the key the user defined for the help tip) a help message can show up. This help message might be the same as the tooltip but in general (if used) this message should show more help. This defines the text of that message.&lt;br /&gt;
|-&lt;br /&gt;
| use_tooltip_on_label_overflow&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If the text on the label is truncated and the tooltip is empty the label can be used for the tooltip. If this variable is set to true this will happen.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_mode&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The mode for showing the debug border. This border shows the area reserved for a widget. This function is only meant for debugging and might not be available in all Wesnoth binaries. Available modes: &lt;br /&gt;
* 0 no border. &lt;br /&gt;
* 1 1 pixel border. &lt;br /&gt;
* 2 floodfill the widget area.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the debug border.&lt;br /&gt;
|-&lt;br /&gt;
| size_text&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Sets the minimum width of the widget depending on the text in it. (Note not implemented yet.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Button ==&lt;br /&gt;
A button is a control that can be pushed to start an action or close a dialog.&lt;br /&gt;
&lt;br /&gt;
Instance of a button. When a button has a return value it sets the&lt;br /&gt;
return value for the window. Normally this closes the window and returns&lt;br /&gt;
this value to the caller. The return value can either be defined by the&lt;br /&gt;
user or determined from the id of the button. The return value has a&lt;br /&gt;
higher precedence as the one defined by the id. (Of course it's weird to&lt;br /&gt;
give a button an id and then override its return value.)&lt;br /&gt;
&lt;br /&gt;
When the button doesn't have a standard id, but you still want to use the&lt;br /&gt;
return value of that id, use return_value_id instead. This has a higher&lt;br /&gt;
precedence as return_value.&lt;br /&gt;
&lt;br /&gt;
List with the button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Supported values for return_value_id:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!string&lt;br /&gt;
!value&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
|&amp;quot;ok&amp;quot;|-1|Equivalent to closing the dialog by pressing the Enter key&lt;br /&gt;
|&amp;quot;cancel&amp;quot;|-2|Equivalent to closing the dialog by pressing the Esc key&lt;br /&gt;
|&amp;quot;quit&amp;quot;|-2|Alias for cancel&lt;br /&gt;
|&amp;quot;&amp;quot;|N/A|Clears any previously set return_value_id&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Combobox ==&lt;br /&gt;
[[File:Combobox.png|frame|right|A Combobox with its list open]]&lt;br /&gt;
A widget with a text box and a dropdown list. Selecting an element from the list sets the value of the text box to that item of the list. The user can also manually enter a value in the text box.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! key !! type !! default !! description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The text of the combobox&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;combobox&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Drawing ==&lt;br /&gt;
A drawing is widget with a fixed size and gives access to the canvas of the widget in the window instance. This allows special display only widgets.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is not zero the drawing functions as a&lt;br /&gt;
fixed size drawing.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| draw&lt;br /&gt;
| [[GUIVariable#config|config]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The config containing the drawing.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Grid Listbox ==&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Horizontal listbox ==&lt;br /&gt;
A horizontal listbox is a control that holds several items of the same type.  Normally the items in a listbox are ordered in rows, this version orders them in columns instead.&lt;br /&gt;
&lt;br /&gt;
List with the horizontal listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a horizontal listbox,&lt;br /&gt;
the widgets need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
An image shows a static image.&lt;br /&gt;
&lt;br /&gt;
An image has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Label ==&lt;br /&gt;
A label displays text that can be wrapped but no scrollbars are provided.&lt;br /&gt;
&lt;br /&gt;
[[File:Title Label.png|frame|right|A Label with definition &amp;quot;title&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
List with the label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| wrap || [[GUIVariable#bool|bool]] || false || Is wrapping enabled for the label.&lt;br /&gt;
|-&lt;br /&gt;
| characters_per_line || [[GUIVariable#unsigned|unsigned]] || 0 || Sets the maximum number of characters per line. The amount is an approximate since the width of a character differs. E.g. iii is smaller than MMM. When the value is non-zero it also implies can_wrap is true. When having long strings wrapping them can increase readability, often 66 characters per line is considered the optimum for a one column text. text_alignment &amp;amp; h_align &amp;amp; &amp;quot;left&amp;quot; &amp;amp; How is the text aligned in the label.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| can_shrink || [[GUIVariable#bool|bool]] || false || Whether the label can shrink past its optimal size.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Listbox ==&lt;br /&gt;
A listbox is a control that holds several items of the same type. Normally the items in a listbox are ordered in rows, this version might allow more options for ordering the items in the future.&lt;br /&gt;
&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a listbox, the widgets&lt;br /&gt;
need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Matrix ==&lt;br /&gt;
List with the matrix specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Menu Button ==&lt;br /&gt;
[[File:Menu Button.png|thumb|left|A Menu Button with it's list open.]]&lt;br /&gt;
A button that shows a dropdown list when clicked. The user can select any one of the predefined options.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;menu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Minimap ==&lt;br /&gt;
A minimap to show the gamemap, this only shows the map and has no interaction options. This version is used for map previews, there will be a another version which allows interaction.&lt;br /&gt;
&lt;br /&gt;
A minimap has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Multiline Text ==&lt;br /&gt;
Base class for a multiline text area.&lt;br /&gt;
&lt;br /&gt;
The following variables exist:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multimenu Button ==&lt;br /&gt;
[[File:Multimenu Button.png|thumb|right|A Multimenu Button with its list open]]&lt;br /&gt;
A widget clicking on which shows a list from which one or more options can be selected.&lt;br /&gt;
&lt;br /&gt;
List with the multimenu_button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value || [[GUIVariable#int|int]] || 0 || The return value.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_shown || [[GUIVariable#int|int]] || -1 || The maximum number of currently selected values to list on the button.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;multimenu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| checkbox || [[GUIVariable#bool|bool]] || &amp;quot;&amp;quot; || Whether the checkbox alongside this option is selected or not.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multi page ==&lt;br /&gt;
A multi page is a control that contains several 'pages' of which only one is visible. The pages can contain the same widgets containing the same 'kind' of data or look completely different.&lt;br /&gt;
&lt;br /&gt;
List with the multi page specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| page_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a multi page item looks. It must contain the grid definition for at least one page.&lt;br /&gt;
|-&lt;br /&gt;
| page_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the multi page. Every row must have the same number of columns as the 'page_definition'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Panel ==&lt;br /&gt;
A panel is an item which can hold other items. The difference between a grid and a panel is that it's possible to define how a panel looks. A grid in an invisible container to just hold the items.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Password box ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the password box.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Progress bar ==&lt;br /&gt;
A progress bar shows the progress of a certain object.&lt;br /&gt;
&lt;br /&gt;
A progress bar has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Repeating button ==&lt;br /&gt;
A repeating_button is a control that can be pushed down and repeat a certain action. Once the button is down every x milliseconds it is down a new down event is triggered.&lt;br /&gt;
&lt;br /&gt;
== Rich Label ==&lt;br /&gt;
A label that shows formatted text marked up with [[Help markup]]. It can show embedded images, links and tables inside text.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#int|int]] || 500 || Width of its internal formatted content. Text will wrap beyond this width.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll label ==&lt;br /&gt;
A scroll label is a label that wraps its text and also has a vertical scrollbar. This way a text can't be too long to be shown for this widget.&lt;br /&gt;
&lt;br /&gt;
List with the scroll label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scrollbar panel ==&lt;br /&gt;
Instance of a scrollbar_panel.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar_panel specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a scrollbar_panel item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Spacer ==&lt;br /&gt;
A spacer is a dummy item to either fill in a widget since no empty items are allowed or to reserve a fixed space.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is non-zero the spacer functions as a&lt;br /&gt;
fixed size spacer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The width of the spacer.&lt;br /&gt;
|-&lt;br /&gt;
| height || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The height of the spacer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Tab Container ==&lt;br /&gt;
&lt;br /&gt;
A container widget that can show its contents separated into various pages, each of which are accessible.&lt;br /&gt;
&lt;br /&gt;
It can contain one or more &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tags inside it, each defining a tab's name, image (if any) and the contents of the tag, specified by the &amp;lt;code&amp;gt;[data]&amp;lt;/code&amp;gt; tag inside the &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
=== Subtag [tab] ===&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| name || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the tab&lt;br /&gt;
|-&lt;br /&gt;
| image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image for the tab to be shown alongside the name, if any&lt;br /&gt;
|-&lt;br /&gt;
| [data] || [[GUIVariable#grid|grid]] || empty grid || This subtag contains a grid that defines the contents for this tab.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text box ==&lt;br /&gt;
A single line text entry widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Text Box.png|frame|right|A Text Box]]&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| editable || [[GUIVariable#bool|bool]] || &amp;quot;true&amp;quot; || If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle panel ==&lt;br /&gt;
A toggle panel is an item which can hold other items. The difference between&lt;br /&gt;
a grid and a panel is that it's possible to define how a panel looks. A grid&lt;br /&gt;
in an invisible container to just hold the items. The toggle panel is a&lt;br /&gt;
combination of the panel and a toggle button, it allows a toggle button with&lt;br /&gt;
its own grid.&lt;br /&gt;
&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Tree view ==&lt;br /&gt;
A tree view is a control that holds several items of the same or different types. The items shown are called tree view nodes and when a node has children, these can be shown or hidden. Nodes that contain children need to provide a clickable button in order to fold or unfold the children.&lt;br /&gt;
&lt;br /&gt;
List with the tree view specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| indention_step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of pixels every level of nodes is indented from the previous level.&lt;br /&gt;
|-&lt;br /&gt;
| node&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The tree view can contain multiple node sections. This part needs more documentation.&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE more documentation and examples are needed.&lt;br /&gt;
&lt;br /&gt;
== Vertical scrollbar ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Viewport ==&lt;br /&gt;
A viewport is an special widget used to view only a part of the widget it `holds'.&lt;br /&gt;
&lt;br /&gt;
List with the viewport specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grow_direction&lt;br /&gt;
| [[GUIVariable#grow_direction|grow_direction]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The direction in which new items grow.&lt;br /&gt;
|-&lt;br /&gt;
| parallel_items&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The number of items that are growing in parallel.&lt;br /&gt;
|-&lt;br /&gt;
| item_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The definition of a new item.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll Text ==&lt;br /&gt;
A multiline text area that shows a scrollbar if the text gets too long.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar container specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of this scroll_text can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slider ==&lt;br /&gt;
&lt;br /&gt;
A slider is a control that can select a value by moving a grip on a groove.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| best_slider_length&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The best length for the sliding part.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The minimum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The maximum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of items the slider's value increases with one step.&lt;br /&gt;
|-&lt;br /&gt;
| value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The value of the slider.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the minimum value is chosen there might be the need for a special value (eg off). When this key has a value that value will be shown if the minimum is selected.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the maximum value is chosen there might be the need for a special value (eg unlimited)). When this key has a value that value will be shown if the maximum is selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle button ==&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73798</id>
		<title>GUIWidgetInstanceWML</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=GUIWidgetInstanceWML&amp;diff=73798"/>
		<updated>2024-09-23T12:42:43Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* MMB Subtag [option] checkbox*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Widget instance ==&lt;br /&gt;
Inside a grid (which is inside all container widgets) a widget is&lt;br /&gt;
instantiated. With this instantiation some more variables of a widget can&lt;br /&gt;
be tuned. This page will describe what can be tuned.&lt;br /&gt;
&lt;br /&gt;
== Widget ==&lt;br /&gt;
All widgets placed in the cell have some values in common:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| This value is used for the engine to identify 'special' items. This means that for example a text_box can get the proper initial value. This value should be unique or empty. Those special values are documented at the window definition that uses them. NOTE items starting with an underscore are used for composed widgets and these should be unique per composed widget.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;default&amp;quot;&lt;br /&gt;
| The id of the widget definition to use. This way it's possible to select a specific version of the widget e.g. a title label when the label is used as title.&lt;br /&gt;
|-&lt;br /&gt;
| linked_group&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The linked group the control belongs to.&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Most widgets have some text associated with them, this field contain the value of that text. Some widgets use this value for other purposes, this is documented at the widget. E.g. an image uses the filename in this field.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget a while (the time it takes can differ per widget) a short help can show up.This defines the text of that message. This field may not be empty when 'help' is set.&lt;br /&gt;
|-&lt;br /&gt;
| help&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If you hover over a widget and press F10 (or the key the user defined for the help tip) a help message can show up. This help message might be the same as the tooltip but in general (if used) this message should show more help. This defines the text of that message.&lt;br /&gt;
|-&lt;br /&gt;
| use_tooltip_on_label_overflow&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If the text on the label is truncated and the tooltip is empty the label can be used for the tooltip. If this variable is set to true this will happen.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_mode&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The mode for showing the debug border. This border shows the area reserved for a widget. This function is only meant for debugging and might not be available in all Wesnoth binaries. Available modes: &lt;br /&gt;
* 0 no border. &lt;br /&gt;
* 1 1 pixel border. &lt;br /&gt;
* 2 floodfill the widget area.&lt;br /&gt;
|-&lt;br /&gt;
| debug_border_color&lt;br /&gt;
| [[GUIVariable#color|color]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The color of the debug border.&lt;br /&gt;
|-&lt;br /&gt;
| size_text&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| Sets the minimum width of the widget depending on the text in it. (Note not implemented yet.)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Button ==&lt;br /&gt;
A button is a control that can be pushed to start an action or close a dialog.&lt;br /&gt;
&lt;br /&gt;
Instance of a button. When a button has a return value it sets the&lt;br /&gt;
return value for the window. Normally this closes the window and returns&lt;br /&gt;
this value to the caller. The return value can either be defined by the&lt;br /&gt;
user or determined from the id of the button. The return value has a&lt;br /&gt;
higher precedence as the one defined by the id. (Of course it's weird to&lt;br /&gt;
give a button an id and then override its return value.)&lt;br /&gt;
&lt;br /&gt;
When the button doesn't have a standard id, but you still want to use the&lt;br /&gt;
return value of that id, use return_value_id instead. This has a higher&lt;br /&gt;
precedence as return_value.&lt;br /&gt;
&lt;br /&gt;
List with the button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Combobox ==&lt;br /&gt;
[[File:Combobox.png|frame|right|A Combobox with its list open]]&lt;br /&gt;
A widget with a text box and a dropdown list. Selecting an element from the list sets the value of the text box to that item of the list. The user can also manually enter a value in the text box.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! key !! type !! default !! description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The text of the combobox&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;combobox&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Drawing ==&lt;br /&gt;
A drawing is widget with a fixed size and gives access to the canvas of the widget in the window instance. This allows special display only widgets.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is not zero the drawing functions as a&lt;br /&gt;
fixed size drawing.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| width&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The width of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| height&lt;br /&gt;
| [[GUIVariable#f_unsigned|f_unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The height of the drawing.&lt;br /&gt;
|-&lt;br /&gt;
| draw&lt;br /&gt;
| [[GUIVariable#config|config]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The config containing the drawing.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Grid Listbox ==&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Horizontal listbox ==&lt;br /&gt;
A horizontal listbox is a control that holds several items of the same type.  Normally the items in a listbox are ordered in rows, this version orders them in columns instead.&lt;br /&gt;
&lt;br /&gt;
List with the horizontal listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!ID (return value)&lt;br /&gt;
!Type&lt;br /&gt;
!Mandatory&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIToolkitWML#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIToolkitWML#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIToolkitWML#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIToolkitWML#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a horizontal listbox,&lt;br /&gt;
the widgets need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Image ==&lt;br /&gt;
An image shows a static image.&lt;br /&gt;
&lt;br /&gt;
An image has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Label ==&lt;br /&gt;
A label displays text that can be wrapped but no scrollbars are provided.&lt;br /&gt;
&lt;br /&gt;
[[File:Title Label.png|frame|right|A Label with definition &amp;quot;title&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
List with the label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| wrap || [[GUIVariable#bool|bool]] || false || Is wrapping enabled for the label.&lt;br /&gt;
|-&lt;br /&gt;
| characters_per_line || [[GUIVariable#unsigned|unsigned]] || 0 || Sets the maximum number of characters per line. The amount is an approximate since the width of a character differs. E.g. iii is smaller than MMM. When the value is non-zero it also implies can_wrap is true. When having long strings wrapping them can increase readability, often 66 characters per line is considered the optimum for a one column text. text_alignment &amp;amp; h_align &amp;amp; &amp;quot;left&amp;quot; &amp;amp; How is the text aligned in the label.&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| can_shrink || [[GUIVariable#bool|bool]] || false || Whether the label can shrink past its optimal size.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Listbox ==&lt;br /&gt;
A listbox is a control that holds several items of the same type. Normally the items in a listbox are ordered in rows, this version might allow more options for ordering the items in the future.&lt;br /&gt;
&lt;br /&gt;
List with the listbox specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| header&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional header. (This grid will automatically get the id _header_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| footer&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| []&lt;br /&gt;
| Defines the grid for the optional footer. (This grid will automatically get the id _footer_grid.)&lt;br /&gt;
|-&lt;br /&gt;
| list_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a listbox item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|-&lt;br /&gt;
| list_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the listbox. Every row must have the same number of columns as the 'list_definition'.&lt;br /&gt;
|-&lt;br /&gt;
| has_minimum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, less than one row can be selected.&lt;br /&gt;
|-&lt;br /&gt;
| has_maximum&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| true&lt;br /&gt;
| If false, more than one row can be selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order to force widgets to be the same size inside a listbox, the widgets&lt;br /&gt;
need to be inside a linked_group.&lt;br /&gt;
&lt;br /&gt;
Inside the list section there are only the following widgets allowed&lt;br /&gt;
* grid (to nest)&lt;br /&gt;
* selectable widgets which are&lt;br /&gt;
** toggle_button&lt;br /&gt;
** toggle_panel&lt;br /&gt;
&lt;br /&gt;
== Matrix ==&lt;br /&gt;
List with the matrix specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Menu Button ==&lt;br /&gt;
[[File:Menu Button.png|thumb|left|A Menu Button with it's list open.]]&lt;br /&gt;
A button that shows a dropdown list when clicked. The user can select any one of the predefined options.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;menu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| icon || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || WML path to the icon to be shown alongside the text in this option, if any.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Minimap ==&lt;br /&gt;
A minimap to show the gamemap, this only shows the map and has no interaction options. This version is used for map previews, there will be a another version which allows interaction.&lt;br /&gt;
&lt;br /&gt;
A minimap has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Multiline Text ==&lt;br /&gt;
Base class for a multiline text area.&lt;br /&gt;
&lt;br /&gt;
The following variables exist:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multimenu Button ==&lt;br /&gt;
[[File:Multimenu Button.png|thumb|right|A Multimenu Button with its list open]]&lt;br /&gt;
A widget clicking on which shows a list from which one or more options can be selected.&lt;br /&gt;
&lt;br /&gt;
List with the multimenu_button specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value || [[GUIVariable#int|int]] || 0 || The return value.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_shown || [[GUIVariable#int|int]] || -1 || The maximum number of currently selected values to list on the button.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Subtag [option] ===&lt;br /&gt;
Specifies the initial list of options to be shown in the &amp;lt;code&amp;gt;multimenu_button&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the option.&lt;br /&gt;
|-&lt;br /&gt;
| tooltip || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Tooltip that is shown when the mouse hovers above this option.&lt;br /&gt;
|-&lt;br /&gt;
| checkbox || [[GUIVariable#bool|bool]] || &amp;quot;&amp;quot; || Whether the checkbox alongside this option is selected or not.&lt;br /&gt;
|-&lt;br /&gt;
| details || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Short description about this option.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Multi page ==&lt;br /&gt;
A multi page is a control that contains several 'pages' of which only one is visible. The pages can contain the same widgets containing the same 'kind' of data or look completely different.&lt;br /&gt;
&lt;br /&gt;
List with the multi page specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| page_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a multi page item looks. It must contain the grid definition for at least one page.&lt;br /&gt;
|-&lt;br /&gt;
| page_data&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| []&lt;br /&gt;
| A grid alike section which stores the initial data for the multi page. Every row must have the same number of columns as the 'page_definition'.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Panel ==&lt;br /&gt;
A panel is an item which can hold other items. The difference between a grid and a panel is that it's possible to define how a panel looks. A grid in an invisible container to just hold the items.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Password box ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The initial text of the password box.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Progress bar ==&lt;br /&gt;
A progress bar shows the progress of a certain object.&lt;br /&gt;
&lt;br /&gt;
A progress bar has no extra fields.&lt;br /&gt;
&lt;br /&gt;
== Repeating button ==&lt;br /&gt;
A repeating_button is a control that can be pushed down and repeat a certain action. Once the button is down every x milliseconds it is down a new down event is triggered.&lt;br /&gt;
&lt;br /&gt;
== Rich Label ==&lt;br /&gt;
A label that shows formatted text marked up with [[Help markup]]. It can show embedded images, links and tables inside text.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| text_alignment || [[GUIVariable#h_align|h_align]] || left || The way the text is aligned inside the canvas.&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#int|int]] || 500 || Width of its internal formatted content. Text will wrap beyond this width.&lt;br /&gt;
|-&lt;br /&gt;
| link_aware || [[GUIVariable#bool|bool]] || false || Whether the label is link aware. This means it is rendered with links highlighted, and responds to click events on those links.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll label ==&lt;br /&gt;
A scroll label is a label that wraps its text and also has a vertical scrollbar. This way a text can't be too long to be shown for this widget.&lt;br /&gt;
&lt;br /&gt;
List with the scroll label specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scrollbar panel ==&lt;br /&gt;
Instance of a scrollbar_panel.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar_panel specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| This defines how a scrollbar_panel item looks. It must contain the grid definition for 1 row of the list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Spacer ==&lt;br /&gt;
A spacer is a dummy item to either fill in a widget since no empty items are allowed or to reserve a fixed space.&lt;br /&gt;
&lt;br /&gt;
If either the width or the height is non-zero the spacer functions as a&lt;br /&gt;
fixed size spacer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| width || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The width of the spacer.&lt;br /&gt;
|-&lt;br /&gt;
| height || [[GUIVariable#f_unsigned|f_unsigned]] || 0 || The height of the spacer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The variable available are the same as for the window resolution see&lt;br /&gt;
http://www.wesnoth.org/wiki/GUIToolkitWML#Resolution_2 for the list of&lt;br /&gt;
items.&lt;br /&gt;
&lt;br /&gt;
== Tab Container ==&lt;br /&gt;
&lt;br /&gt;
A container widget that can show its contents separated into various pages, each of which are accessible.&lt;br /&gt;
&lt;br /&gt;
It can contain one or more &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tags inside it, each defining a tab's name, image (if any) and the contents of the tag, specified by the &amp;lt;code&amp;gt;[data]&amp;lt;/code&amp;gt; tag inside the &amp;lt;code&amp;gt;[tab]&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
=== Subtag [tab] ===&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| name || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || Name of the tab&lt;br /&gt;
|-&lt;br /&gt;
| image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image for the tab to be shown alongside the name, if any&lt;br /&gt;
|-&lt;br /&gt;
| [data] || [[GUIVariable#grid|grid]] || empty grid || This subtag contains a grid that defines the contents for this tab.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Text box ==&lt;br /&gt;
A single line text entry widget.&lt;br /&gt;
&lt;br /&gt;
[[File:Text Box.png|frame|right|A Text Box]]&lt;br /&gt;
&lt;br /&gt;
{| class = &amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key !!type !!default !!description&lt;br /&gt;
|-&lt;br /&gt;
| label || [[GUIVariable#t_string|t_string]] || &amp;quot;&amp;quot; || The initial text of the text box.&lt;br /&gt;
|-&lt;br /&gt;
| history || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || The name of the history for the text box. A history saves the data entered in a text box between the games. With the up and down arrow it can be accessed. To create a new history item just add a new unique name for this field and the engine will handle the rest.&lt;br /&gt;
|-&lt;br /&gt;
| max_input_length || [[GUIVariable#int|int]] || 0 || Maximum length of text in characters that can be entered into the combobox&lt;br /&gt;
|-&lt;br /&gt;
| hint_text || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Text that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| hint_image || [[GUIVariable#string|string]] || &amp;quot;&amp;quot; || Image that is shown in the background when there is no input&lt;br /&gt;
|-&lt;br /&gt;
| editable || [[GUIVariable#bool|bool]] || &amp;quot;true&amp;quot; || If the contents of the text box can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle panel ==&lt;br /&gt;
A toggle panel is an item which can hold other items. The difference between&lt;br /&gt;
a grid and a panel is that it's possible to define how a panel looks. A grid&lt;br /&gt;
in an invisible container to just hold the items. The toggle panel is a&lt;br /&gt;
combination of the panel and a toggle button, it allows a toggle button with&lt;br /&gt;
its own grid.&lt;br /&gt;
&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value, see [[GUIToolkitWML#Button]] for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Tree view ==&lt;br /&gt;
A tree view is a control that holds several items of the same or different types. The items shown are called tree view nodes and when a node has children, these can be shown or hidden. Nodes that contain children need to provide a clickable button in order to fold or unfold the children.&lt;br /&gt;
&lt;br /&gt;
List with the tree view specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| indention_step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of pixels every level of nodes is indented from the previous level.&lt;br /&gt;
|-&lt;br /&gt;
| node&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The tree view can contain multiple node sections. This part needs more documentation.&lt;br /&gt;
|-&lt;br /&gt;
| id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| .&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NOTE more documentation and examples are needed.&lt;br /&gt;
&lt;br /&gt;
== Vertical scrollbar ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Viewport ==&lt;br /&gt;
A viewport is an special widget used to view only a part of the widget it `holds'.&lt;br /&gt;
&lt;br /&gt;
List with the viewport specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grow_direction&lt;br /&gt;
| [[GUIVariable#grow_direction|grow_direction]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The direction in which new items grow.&lt;br /&gt;
|-&lt;br /&gt;
| parallel_items&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The number of items that are growing in parallel.&lt;br /&gt;
|-&lt;br /&gt;
| item_definition&lt;br /&gt;
| [[GUIVariable#section|section]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| The definition of a new item.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scroll Text ==&lt;br /&gt;
A multiline text area that shows a scrollbar if the text gets too long.&lt;br /&gt;
&lt;br /&gt;
List with the scrollbar container specific variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| vertical_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| horizontal_scrollbar_mode&lt;br /&gt;
| [[GUIVariable#scrollbar_mode|scrollbar_mode]]&lt;br /&gt;
| initial_auto&lt;br /&gt;
| Determines whether or not to show the scrollbar.&lt;br /&gt;
|-&lt;br /&gt;
| editable&lt;br /&gt;
| [[GUIVariable#bool|bool]]&lt;br /&gt;
| &amp;quot;true&amp;quot;&lt;br /&gt;
| If the contents of this scroll_text can be edited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Slider ==&lt;br /&gt;
&lt;br /&gt;
A slider is a control that can select a value by moving a grip on a groove.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| best_slider_length&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The best length for the sliding part.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The minimum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The maximum value the slider can have.&lt;br /&gt;
|-&lt;br /&gt;
| step_size&lt;br /&gt;
| [[GUIVariable#unsigned|unsigned]]&lt;br /&gt;
| 0&lt;br /&gt;
| The number of items the slider's value increases with one step.&lt;br /&gt;
|-&lt;br /&gt;
| value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The value of the slider.&lt;br /&gt;
|-&lt;br /&gt;
| minimum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the minimum value is chosen there might be the need for a special value (eg off). When this key has a value that value will be shown if the minimum is selected.&lt;br /&gt;
|-&lt;br /&gt;
| maximum_value_label&lt;br /&gt;
| [[GUIVariable#t_string|t_string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| If the maximum value is chosen there might be the need for a special value (eg unlimited)). When this key has a value that value will be shown if the maximum is selected.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Toggle button ==&lt;br /&gt;
Variables:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!key&lt;br /&gt;
!type&lt;br /&gt;
!default&lt;br /&gt;
!description&lt;br /&gt;
|-&lt;br /&gt;
| grid&lt;br /&gt;
| [[GUIVariable#grid|grid]]&lt;br /&gt;
| mandatory&lt;br /&gt;
| Defines the grid with the widgets to place on the panel.&lt;br /&gt;
|-&lt;br /&gt;
| return_value_id&lt;br /&gt;
| [[GUIVariable#string|string]]&lt;br /&gt;
| &amp;quot;&amp;quot;&lt;br /&gt;
| The return value id.&lt;br /&gt;
|-&lt;br /&gt;
| return_value&lt;br /&gt;
| [[GUIVariable#int|int]]&lt;br /&gt;
| 0&lt;br /&gt;
| The return value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: WML Reference]]&lt;br /&gt;
[[Category: GUI WML Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73785</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73785"/>
		<updated>2024-09-22T12:33:16Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Definitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui - Mostly about opening windows]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget|LuaAPI/types/widget - Widget attributes and callbacks]]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73784</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73784"/>
		<updated>2024-09-22T11:54:08Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Definitions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.tag.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui - Mostly about opening windows]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget|LuaAPI/types/widget - Widget attributes and callbacks]]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/gui/widget&amp;diff=73773</id>
		<title>LuaAPI/gui/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/gui/widget&amp;diff=73773"/>
		<updated>2024-09-21T17:59:12Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: removed reference to negative index to add_item_of_type (has been removed, never worked anyway)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
The '''gui.widget''' module contains functions for managing widgets in custom GUI2 dialogs. Since these functions take a [[LuaAPI/types/widget|widget userdata]] as the first parameter, they can only be used in the preshow or postshow of a GUI2 dialog (directly or indirectly). However, the table is available at all times, and additional methods can be installed here for unusual needs.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The '''gui.widget.set_callback''' is a compatibility wrapper and is unsupported. It may be removed without warning. Callbacks should be bound by assigning the appropriate callback key on the widget.&lt;br /&gt;
&lt;br /&gt;
=== focus ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.focus'''(''widget'')&lt;br /&gt;
* ''widget'':'''focus'''()&lt;br /&gt;
&lt;br /&gt;
Switches the keyboard focus to the widget. This is often useful for dialogs containing a central listbox, so that it can be controlled with the keyboard as soon as it is displayed.&lt;br /&gt;
&lt;br /&gt;
=== set_canvas ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.set_canvas'''(''widget'', ''layer index'', ''content'')&lt;br /&gt;
* ''widget'':'''set_canvas'''(''layer index'', ''content'')&lt;br /&gt;
&lt;br /&gt;
Sets the WML passed as the second argument as the canvas content (index given by the first argument) of the widget. The content of the WML table depends on which shape is used:&lt;br /&gt;
&lt;br /&gt;
* [[GUICanvasWML#Circle|Circle]]&lt;br /&gt;
* [[GUICanvasWML#Image|Image]]&lt;br /&gt;
* [[GUICanvasWML#Line|Line]]&lt;br /&gt;
* [[GUICanvasWML#Bounded_Shape|common attributes of rectangles, round rectangles and text]]&lt;br /&gt;
* [[GUICanvasWML#Rectangle|Rectangle]]&lt;br /&gt;
* [[GUICanvasWML#Rounded_Rectangle|Rounded Rectangle]]&lt;br /&gt;
* [[GUICanvasWML#Text|Text]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
-- draw two rectangles in the upper-left corner of the window (assume dialog is the window widget)&lt;br /&gt;
dialog:set_canvas(2, {&lt;br /&gt;
    wml.tag.rectangle { x = 20, y = 20, w = 20, h = 20, fill_color= &amp;quot;0,0,255,255&amp;quot; },&lt;br /&gt;
    wml.tag.rectangle { x = 30, y = 30, w = 20, h = 20, fill_color = &amp;quot;255,0,0,255&amp;quot; }&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the canvas index depends on the chosen widget. It may be the disabled / enabled states of the widget, or its background / foreground planes, or... For instance, overwriting canvas 1 of the window with an empty canvas causes the window to become transparent.&lt;br /&gt;
&lt;br /&gt;
=== add_item ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.add_item'''(''widget'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
* ''widget'':'''add_item'''([''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
&lt;br /&gt;
Add an item to a container widget, for example a listbox. Returns the created item as a [[LuaAPI/types/widget|widget userdata]].&lt;br /&gt;
&lt;br /&gt;
=== add_item_of_type ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.add_item_of_type'''(''widget'', ''category'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
* ''widget'':'''add_item_of_type'''(''category'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
&lt;br /&gt;
Add an item to a widget which is a heterogeneous container of different types of widgets, in particular multi_pages and treeviews.&lt;br /&gt;
&lt;br /&gt;
=== remove_items_at ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.remove_items_at'''(''widget'', ''position'', ''count'')&lt;br /&gt;
* ''widget'':'''remove_items_at'''(''position'', ''count'')&lt;br /&gt;
&lt;br /&gt;
Removes one or more elements of a container type widget (like treeviews), starting at the given index. If 0 is passed as the count, all elements from that point to the end are removed. Otherwise, the specified number of elements are removed.&lt;br /&gt;
&lt;br /&gt;
=== find ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.find'''(''root widget'', ...)&lt;br /&gt;
* ''widget'':'''find'''(...)&lt;br /&gt;
&lt;br /&gt;
Finds a child widget of the widget of the given path. For example, here it searches for the widget with the id 'preview_panel' of the second item of the widget with the id 'unit_list':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog:find('unit_list', 2, 'preview_panel')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is more or less equivalent to the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.unit_list[2].preview_panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, if the path comes from a variable, the functional form may be more convenient:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog:find(table.unpack(path))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== close ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.close'''(''dialog'')&lt;br /&gt;
* ''widget'':'''close'''()&lt;br /&gt;
&lt;br /&gt;
Closes the dialog.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LuaAPI/gui/widget&amp;diff=73772</id>
		<title>LuaAPI/gui/widget</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LuaAPI/gui/widget&amp;diff=73772"/>
		<updated>2024-09-21T17:58:40Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: removed reference to negative index to add_item (has been removed, never worked anyway)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
The '''gui.widget''' module contains functions for managing widgets in custom GUI2 dialogs. Since these functions take a [[LuaAPI/types/widget|widget userdata]] as the first parameter, they can only be used in the preshow or postshow of a GUI2 dialog (directly or indirectly). However, the table is available at all times, and additional methods can be installed here for unusual needs.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The '''gui.widget.set_callback''' is a compatibility wrapper and is unsupported. It may be removed without warning. Callbacks should be bound by assigning the appropriate callback key on the widget.&lt;br /&gt;
&lt;br /&gt;
=== focus ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.focus'''(''widget'')&lt;br /&gt;
* ''widget'':'''focus'''()&lt;br /&gt;
&lt;br /&gt;
Switches the keyboard focus to the widget. This is often useful for dialogs containing a central listbox, so that it can be controlled with the keyboard as soon as it is displayed.&lt;br /&gt;
&lt;br /&gt;
=== set_canvas ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.set_canvas'''(''widget'', ''layer index'', ''content'')&lt;br /&gt;
* ''widget'':'''set_canvas'''(''layer index'', ''content'')&lt;br /&gt;
&lt;br /&gt;
Sets the WML passed as the second argument as the canvas content (index given by the first argument) of the widget. The content of the WML table depends on which shape is used:&lt;br /&gt;
&lt;br /&gt;
* [[GUICanvasWML#Circle|Circle]]&lt;br /&gt;
* [[GUICanvasWML#Image|Image]]&lt;br /&gt;
* [[GUICanvasWML#Line|Line]]&lt;br /&gt;
* [[GUICanvasWML#Bounded_Shape|common attributes of rectangles, round rectangles and text]]&lt;br /&gt;
* [[GUICanvasWML#Rectangle|Rectangle]]&lt;br /&gt;
* [[GUICanvasWML#Rounded_Rectangle|Rounded Rectangle]]&lt;br /&gt;
* [[GUICanvasWML#Text|Text]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
-- draw two rectangles in the upper-left corner of the window (assume dialog is the window widget)&lt;br /&gt;
dialog:set_canvas(2, {&lt;br /&gt;
    wml.tag.rectangle { x = 20, y = 20, w = 20, h = 20, fill_color= &amp;quot;0,0,255,255&amp;quot; },&lt;br /&gt;
    wml.tag.rectangle { x = 30, y = 30, w = 20, h = 20, fill_color = &amp;quot;255,0,0,255&amp;quot; }&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the canvas index depends on the chosen widget. It may be the disabled / enabled states of the widget, or its background / foreground planes, or... For instance, overwriting canvas 1 of the window with an empty canvas causes the window to become transparent.&lt;br /&gt;
&lt;br /&gt;
=== add_item ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.add_item'''(''widget'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
* ''widget'':'''add_item'''([''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
&lt;br /&gt;
Add an item to a container widget, for example a listbox. Returns the created item as a [[LuaAPI/types/widget|widget userdata]].&lt;br /&gt;
&lt;br /&gt;
=== add_item_of_type ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.add_item_of_type'''(''widget'', ''category'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
* ''widget'':'''add_item_of_type'''(''category'', [''position'']) &amp;amp;rarr; ''the new item'', ''position''&lt;br /&gt;
&lt;br /&gt;
Add an item to a widget which is a heterogeneous container of different types of widgets, in particular multi_pages and treeviews. You can pass a negative position to count from the end of the container, but the returned position is always positive.&lt;br /&gt;
&lt;br /&gt;
=== remove_items_at ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.remove_items_at'''(''widget'', ''position'', ''count'')&lt;br /&gt;
* ''widget'':'''remove_items_at'''(''position'', ''count'')&lt;br /&gt;
&lt;br /&gt;
Removes one or more elements of a container type widget (like treeviews), starting at the given index. If 0 is passed as the count, all elements from that point to the end are removed. Otherwise, the specified number of elements are removed.&lt;br /&gt;
&lt;br /&gt;
=== find ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.find'''(''root widget'', ...)&lt;br /&gt;
* ''widget'':'''find'''(...)&lt;br /&gt;
&lt;br /&gt;
Finds a child widget of the widget of the given path. For example, here it searches for the widget with the id 'preview_panel' of the second item of the widget with the id 'unit_list':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog:find('unit_list', 2, 'preview_panel')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is more or less equivalent to the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.unit_list[2].preview_panel&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, if the path comes from a variable, the functional form may be more convenient:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog:find(table.unpack(path))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== close ===&lt;br /&gt;
&lt;br /&gt;
* '''gui.widget.close'''(''dialog'')&lt;br /&gt;
* ''widget'':'''close'''()&lt;br /&gt;
&lt;br /&gt;
Closes the dialog.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua Reference]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73643</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73643"/>
		<updated>2024-09-05T07:16:42Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Explore Your Options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.tag.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.toggle_button {&lt;br /&gt;
                    definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.toggle_button {&lt;br /&gt;
                    definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
Note: The keys in the schema file correspond to the attributes used when configuring your widgets.  They will not always align perfectly with keys used by the Lua API.  For example, the slider uses maximum_value in its configuration, and max_value when using the Lua API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[slider]&lt;br /&gt;
    id=&amp;quot;my_slider&amp;quot;&lt;br /&gt;
    maximum_value = 100&lt;br /&gt;
[/slider]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
dialog.my_slider.max_value = 90&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui - Mostly about opening windows]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget|LuaAPI/types/widget - Widget attributes and callbacks]]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73642</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73642"/>
		<updated>2024-09-05T06:56:47Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Building a Tree */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false) when the button is checked (selected == true).  Then we add three &amp;quot;details_node&amp;quot; nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.tag.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.toggle_button {&lt;br /&gt;
                    definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.toggle_button {&lt;br /&gt;
                    definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui - Mostly about opening windows]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget|LuaAPI/types/widget - Widget attributes and callbacks]]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73590</id>
		<title>Sandbox/GUI/Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=Sandbox/GUI/Getting_Started&amp;diff=73590"/>
		<updated>2024-09-01T16:21:49Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Placement */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, it looks like I can't exclude this page/section from the search engine as I had hoped.  I wanted to put this in a sandbox so that it wouldn't be published without some proper review.  &lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
This guide is designed to help you get a simple Wesnoth GUI, implemented in lua, up and running while describing the basic building blocks along the way. It is written in a narrative format, where most examples build on previous examples, and therefore while not always necessary it may be desirable to read from start to finish.  The reader, probably a UMC author, should have a basic knowledge of working with lua within Wesnoth.&lt;br /&gt;
&lt;br /&gt;
Some would find creating a GUI in part or in full using WML simpler to follow, and those alternatives are available, for example [[LuaAPI/gui/example]], but we're using lua here.  If you find WML easier to follow, you can always convert the lua tables that define the GUIs to WML using [[LuaAPI/wml#wml.tostring|wml.tostring]], for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring(dialogDefinition))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In some examples, instead of defining the entire GUI at once, we'll break out some parts into separate variables.  If you try to view one in WML and get an error from wml.tostring() about expecting a WML table and not a table, try passing your variable(/table) inside a table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
print(wml.tostring({listboxItem}))&lt;br /&gt;
gui.show_lua_console()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One distinct advantage of using WML to define your GUI layout is that you get better (any) validation.  Invalid keys, and sometimes values, are often flagged in the log, unlike with lua where they are silently ignored.  In the comments of our first GUI, below, is an example which loads a WML GUI configuration using [[LuaAPI/wml#wml.load|wml.load()]], validating against the GUI2 window schema.&lt;br /&gt;
&lt;br /&gt;
===What is GUI2?===&lt;br /&gt;
Once upon a time, Wesnoth had a GUI system which is now commonly referred to as GUI1.  As of 1.19, GUI1 has been almost completely replaced by GUI2.  UMC authors will probably never encounter GUI1 and can simply use the terms GUI and GUI2 interchangeably, at least until GUI3 comes along.&lt;br /&gt;
&lt;br /&gt;
Instead of spending a lot of time here giving an overview of what GUI2 is and what makes it great, and not so great, let's charge ahead so we can see it in action, and let readers who are interested look elsewhere(TODO: link) for a more formal definition.  (TODO: is this the right approach for most readers?).&lt;br /&gt;
&lt;br /&gt;
==Getting Started==&lt;br /&gt;
&lt;br /&gt;
For example purposes, we'll create a directory in our campaign directory called lua containing a file called gui_tutorial.lua, and add a command in the prestart event for a scenario which will create a right-click menu option to invoke our new GUI.  Of course there are other methods to invoke lua from WML, but this one will get us started.  After all, we really just want to get something up on the screen ASAP, right?&lt;br /&gt;
&lt;br /&gt;
===A most basic GUI===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|[[File:Most basic gui.png|center|thumb|I can't believe this worked]]&lt;br /&gt;
|-&lt;br /&gt;
|In our prestart event, we create a simple menu item, which executes a single line of lua which calls the lua function most_basic_gui() which is found in gui_tutorial.lua:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[set_menu_item]&lt;br /&gt;
   id=most_basic_gui&lt;br /&gt;
   description=&amp;quot;Our first GUI&amp;quot;&lt;br /&gt;
   [command]&lt;br /&gt;
       [lua]&lt;br /&gt;
           code=&amp;lt;&amp;lt;&lt;br /&gt;
                   wesnoth.require(&amp;quot;~add-ons/&amp;lt;OUR_CAMPAIGN&amp;gt;/lua/gui_tutorial.lua&amp;quot;).most_basic_gui()&lt;br /&gt;
                &amp;gt;&amp;gt;&lt;br /&gt;
       [/lua]&lt;br /&gt;
    [/command]&lt;br /&gt;
[/set_menu_item]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And create gui_tutorial.lua:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
! !! The WML equivalent of dialogDefinition&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        --click_dismiss = true, -- allow user to close dialog with click of a button&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },  -- required&lt;br /&gt;
        wml.tag.grid {   -- our most basic gui&lt;br /&gt;
            wml.tag.row {  -- a grid must include at least one row&lt;br /&gt;
                wml.tag.column {  -- a row needs a column&lt;br /&gt;
                    wml.tag.image {  -- a column includes exactly one widget&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
       &lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        print(wml.tostring(dialogDefinition))&lt;br /&gt;
            gui.show_lua_console()&lt;br /&gt;
        end&lt;br /&gt;
        gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
        -- Or, if you want to define the gui in WML, something like:&lt;br /&gt;
        -- local dialog_wml = wml.load(&amp;quot;~add-ons/GUI_Tutorial/most_basic_gui.cfg&amp;quot;,&lt;br /&gt;
        --     true, &amp;quot;schema/gui_window.cfg&amp;quot;)&lt;br /&gt;
        -- gui.show_dialog(wml.get_child(dialog_wml, 'resolution'))&lt;br /&gt;
end&lt;br /&gt;
return { most_basic_gui = most_basic_gui}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[tooltip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/tooltip]&lt;br /&gt;
[helptip]&lt;br /&gt;
    id=&amp;quot;tooltip_large&amp;quot;&lt;br /&gt;
[/helptip]&lt;br /&gt;
[grid]&lt;br /&gt;
    [row]&lt;br /&gt;
        [column]&lt;br /&gt;
            [image]&lt;br /&gt;
                label=&amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
            [/image]&lt;br /&gt;
        [/column]&lt;br /&gt;
    [/row]&lt;br /&gt;
[/grid]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the above file, we have just the single function to create our GUI, followed by a return command which makes our function most_basic_gui() available to the [[LuaAPI/wesnoth#wesnoth.require|wesnoth.require()]] function as most_basic_gui().  &lt;br /&gt;
&lt;br /&gt;
Our function creates a table containing the definition of a &amp;quot;dialog&amp;quot;, and then passes that to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]].  It should be noted that gui.show_dialog does not provide synchronization, so if your GUI makes changes to the game state, you'll need to jump through some hoops or you'll break replays and multiplayer, but that's not something we need to care about at this point, so just be aware that you may need to deal with it in the future.&lt;br /&gt;
&lt;br /&gt;
Our dialog definition at this point includes three parts.  The first two are a tooltip and a helptip, which are required and define how tooltips (use id = &amp;quot;tooltip_large&amp;quot; or id = &amp;quot;tooltip&amp;quot; or id = &amp;quot;tooltip_transparent&amp;quot;), and helptips (rarely used, but must be included here, and yes their definitions are &amp;quot;tooltip&amp;quot; not &amp;quot;helptip&amp;quot;) will look (as we will see later, this really should be definition = &amp;quot;tooltip&amp;quot;, but in this case it's id = &amp;quot;tooltip&amp;quot;).  The third part is a grid, which is basically a table, like in HTML or MySQL, with rows and columns.  A grid always contains at least one row.  A row contains at least one column (note that a column does NOT span rows, it is completely contained within a row).  Inside a column is exactly one item, a cell which contains a [[GUIWidgetDefinitionWML|widget]], in this case we'll use an image (later we'll see what else we can put in a cell).  Note that we don't actually define a cell in our code, it's just a term used to refer to the contents of a column.&lt;br /&gt;
&lt;br /&gt;
The preshow function is optional.  If included in the call to [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]], it is run before the GUI is displayed.  In this case, we include it to display the dialog we created with lua in WML format.  Near the end, in comments, we show how you would call [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] if you chose to define your dialog using WML.  Note that what is shown here is the WML equivalent of our lua dialogDefinition, and not the complete WML you would need to use if you were to configure your GUI layout in WML.&lt;br /&gt;
&lt;br /&gt;
Note: if you should try out the above, you'll have to hit escape or enter to close the GUI.  Uncomment the &amp;quot;click_dismiss&amp;quot; line, and the user will be able to close the GUI with a mouse click.&lt;br /&gt;
&lt;br /&gt;
===Adding a little flavor===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|You may have noticed our GUI is missing a header and a way to close it when we're done admiring our work.  Here we add a new first row to our grid, while demonstrating a couple formatting options: a border to put some distance between our grid cell and its neighbor, and the &amp;quot;use_markup = true&amp;quot; option to enable Pango support in our text.  &lt;br /&gt;
&lt;br /&gt;
Our third row adds an OK button at the bottom.  You can associate actions with buttons to do all kinds of things, but here we just exploit the default behaviour to close the GUI.&lt;br /&gt;
&lt;br /&gt;
Of course, we'll also have to modify our return to support the new function, and update our menu item(s) accordingly. &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui2.png|center|thumb|Adding header and a footer]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui2()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                                  -- but it will close the GUI&lt;br /&gt;
                    wml.tag.button {                              &lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,                                                                           &lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end                                                                                                                    &lt;br /&gt;
return { most_basic_gui = most_basic_gui, most_basic_gui2 = most_basic_gui2 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===And a bit more===&lt;br /&gt;
{|&lt;br /&gt;
&lt;br /&gt;
|And now a minor, but important change.  We want to add a new text field next to the image in the body of our GUI.  Obviously, we want to add a new column, but this is more difficult than when we added new rows in the previous example.  The problem is that all rows (at a given level) in a grid must contain the same number of columns.  We can't have two columns in the row that constitutes the body of our GUI, but only one in the header and one in the footer.  To solve this problem, we replace our image widget with a new grid, which can use as many columns as we like (as long as they are the same within each row of our new grid).  This new grid contains a row with two columns, but that is okay because the new grid itself is placed in a single column, which matches our single column header and footer (ok button), keeping the rows balanced.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Most basic gui3.png|center|thumb|Rows with different numbers of columns]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function most_basic_gui3()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;helptip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {  -- This is the only column in this row, &lt;br /&gt;
                                  -- to match the number of columns in &lt;br /&gt;
                                  -- the rows of our header and footer&lt;br /&gt;
                    wml.tag.grid {  -- A new grid, so we can use a different &lt;br /&gt;
                                    -- number of columns&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.image {&lt;br /&gt;
                                    label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                        wml.tag.column {&lt;br /&gt;
                            wml.tag.label {&lt;br /&gt;
                                label = &amp;quot;A troll&amp;quot;&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.row {  -- A footer&lt;br /&gt;
            wml.tag.column {  -- An &amp;quot;OK&amp;quot; button, with no action assigned for now,&lt;br /&gt;
                              -- but it will close the GUI&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = &amp;quot;Ok&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While we see here just the simplest of examples, you can many levels of grids in grids, rows with multiple columns some of which containing grids, etc, to build complicated dialogs to your liking.&lt;br /&gt;
&lt;br /&gt;
==Containers==&lt;br /&gt;
&lt;br /&gt;
===Stacked Widget===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
===Listbox===&lt;br /&gt;
{|&lt;br /&gt;
| Now we'd like to add some more monsters.  Obviously, we could just add more rows, but what if we won't know until runtime how many and which ones?  We could break up the definition of our dialog and add new rows dynamically, it's just a table after all, but fortunately we have a widget which handles this for us, a listbox.  A listbox is kind of like an array, a collection of similar objects where the number of items can vary.  We will tell the GUI where we want the box, and what each entry in the box will look like, and then at runtime we can add entries to the box.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui with listbox.png|center|thumb|Listbox with three items]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function gui_with_listbox()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          string = &amp;quot;A troll&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A cuttlefish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;,&lt;br /&gt;
          string = &amp;quot;A yeti&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.label {&lt;br /&gt;
                    id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listboxDefinition = wml.tag.listbox { id = listbox_id,&lt;br /&gt;
        wml.tag.list_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_panel {&lt;br /&gt;
                        listboxItem&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            use_markup = true,&lt;br /&gt;
                            label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                                &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                                _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    listboxDefinition&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.button {&lt;br /&gt;
                    id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                    label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i, monster in ipairs(monsters) do&lt;br /&gt;
                listbox[i].monster_image.label = monster.image&lt;br /&gt;
                listbox[i].monster_label.label = monster.string&lt;br /&gt;
            end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by creating a simple table which represents the data which will be presented in our listbox.  In most cases, we probably wouldn't create that monster table here, but we need it for our example.&lt;br /&gt;
&lt;br /&gt;
The variable listbox_id gives us an identifier for our listbox so we can reference it when we need to.  We don't really need to use a variable here, it's just convenient.&lt;br /&gt;
&lt;br /&gt;
We define the structure for the elements in our listbox, stored in listboxItem.  Note that we've replaced the actual data with identifiers (e.g. 'units/trolls/grunt.png' becomes 'id = &amp;quot;monster_image&amp;quot;), since each element may have different data.&lt;br /&gt;
&lt;br /&gt;
We define the listbox itself, specifying the identifier, and the definition of our listbox element (which looks a lot like a grid).  The cell inside the column contains a variable which is just the listbox element definition we created above; it's not necessary to do this, we could have used one big table, but it's easier to read this way (IMO).&lt;br /&gt;
&lt;br /&gt;
We replace the hardcoded data in our GUI body with our new listbox definition, again using a variable to make it easier to read.&lt;br /&gt;
&lt;br /&gt;
We create a function, often called preshow(), which will be called for us as part of the drawing the GUI (see the new optional argument in [[LuaAPI/gui#gui.show_dialog|gui.show_dialog()]] -- there's also an optional postshow(), but we don't need it here).  This is where we pull the data from our example table into the listbox.  We create a listbox variable associated with the listbox, identified by the listbox_id we assigned earlier, inside the dialog which gui.show_dialog() passes to preshow().  Then we iterate through our data table, using each entry from that table to populate a listbox item.&lt;br /&gt;
&lt;br /&gt;
Let's look at that last action a little more closely using an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
listbox[i].monster_image.label = monster.image&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which we can read as &amp;quot;In listbox element i of our listbox, for the image with identifier monster_image which we defined in our listboxItem, use the data from the corresponding index i in our example data table&amp;quot; (you don't see the index i for the monsters table here, but remember we're iterating using ipairs, we could have just as easily used listbox[i].monster_image.label = monsters[i].image).  If you were to step through all of the variable substitutions, you'd see that for i=1, our dialogDefinition is basically the same thing as it was in the earlier examples, just supplied from a table instead of hardcoded (note that you can hardcode entries in a listbox in your dialog definition using the [list_data] tag, aka wml.tag.list_data, which we do not demonstrate here).&lt;br /&gt;
&lt;br /&gt;
You will probably notice that our data does not line up nicely in the GUI.  We will fix that later.  We'll also demonstrate how the user can select an item in a listbox, and how you can identify which item that was using the selected_index variable of the listbox.&lt;br /&gt;
&lt;br /&gt;
===Tree View===&lt;br /&gt;
====Simple Tree View====&lt;br /&gt;
{| &lt;br /&gt;
| You may have noticed that clicking on a listbox item in our listbox caused it to be highlighted with a box around the contents.  This is because the items in a listbox are selectable.  This will be useful when we want to add actions, but it looks a bit odd if we just want to present a list of data.&lt;br /&gt;
&lt;br /&gt;
Also, most of the data had to be formatted the same for each item in the listbox.  We could, perhaps, include custom markup in our labels, but the actual layout, like the number of columns per row, had to be the same for every item.&lt;br /&gt;
&lt;br /&gt;
Another way to present a list of data is the tree view.  Since a tree view supports multiple data types, we may need to create multiple definitions for the elements in our list.  These are known as nodes.  It will also be necessary to explicitly define which node to use for each element when we populate our tree view.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view.png|center|thumb|Tree_views can hold multiple data types (only trolls have names here)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function basic_tree_view()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;, type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;trolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;nottrolls_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                            linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_name&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
            fixed_width = true&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        for i, monster in ipairs(monsters) do&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;trolls_node&amp;quot;)&lt;br /&gt;
                dialog.monsters_tv[i].monster_name.label = monster.name  -- only trolls have a name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_tv:add_item_of_type(&amp;quot;nottrolls_node&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            -- All of our monsters have an image and a label&lt;br /&gt;
            dialog.monsters_tv[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_tv[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have expanded our list of monsters to include three types of trolls.  We have also given each troll a name.  This is of course a rather simplistic example, we could have simply given each monster that is not a troll an empty name, but it as presented here our approach serves the purpose of demonstrating how we deal with multiple data types.  Our new tree view contains a node for each type of data we will present.  In preshow, we explicitly define each element in our list using add_item_of_type(), and populate the item accordingly.  [Note: in our listbox example, we could have used add_item() to add items to the listbox, but chose not to since that section was already introducing a number of new concepts.  But here, since we have multiple types of items we need to be able to specify the type of the item when we add one, hence we need to use add_item_of_type()].&lt;br /&gt;
&lt;br /&gt;
You may also note the addition of a few linked_group lines.  We'll cover linked groups in more detail later, but as used here they instruct the GUI that each column using the same node type needs to be aligned with the others.  For example, all of our trolls line up nicely.&lt;br /&gt;
&lt;br /&gt;
====Building a Tree====&lt;br /&gt;
{|&lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; |At this point, one may wonder about the name &amp;quot;tree view&amp;quot;, since what he have seen doesn't look much like a tree.  To make a tree-like structure, we'll demonstrate adding children to nodes.  At the top level our (upside-down) tree will have two nodes, one for trolls and one for everything else.  A toggle_button (a type of button which changes states when you push it) will allow us to expand the trolls node to expose its children, which are themselves nodes, though they only contain a label at this point.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2a.png|center|thumb|Tree_view with Trolls folded]] || [[File:Basic tree view2b.png|center|thumb|Tree_view with Trolls unfolded]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua line&amp;gt;&lt;br /&gt;
local function building_a_tree()&lt;br /&gt;
    local tree_view = wml.tag.tree_view {&lt;br /&gt;
        id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.toggle_button {&lt;br /&gt;
                            id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.node {&lt;br /&gt;
            id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
            wml.tag.node_definition {&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Show me the &amp;quot; ..&lt;br /&gt;
                        &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                        _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    tree_view&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
        -- You can refer to an object by its position&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1].race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.on_modified =    &lt;br /&gt;
        --    function()dialog.monsters_tv[1].unfolded = &lt;br /&gt;
        -- dialog.monsters_tv[1].race_button.selected end&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][1].monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][2].monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[1]:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[1][3].monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        -- dialog.monsters_tv[2].race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        -- dialog.monsters_tv[2].race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        -- ... or you can refer to that object using the return value&lt;br /&gt;
        --    from add_item_of_type&lt;br /&gt;
        local troll_node = dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        troll_node.race_label.label = &amp;quot;Trolls&amp;quot;&lt;br /&gt;
        troll_node.race_button.on_modified = &lt;br /&gt;
            function()&lt;br /&gt;
                troll_node.unfolded = troll_node.race_button.selected &lt;br /&gt;
            end&lt;br /&gt;
        local item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Whelp&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Shaman&amp;quot;&lt;br /&gt;
        item = troll_node:add_item_of_type(&amp;quot;details_node&amp;quot;)&lt;br /&gt;
        item.monster_type.label = &amp;quot;Troll&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        local not_troll_node = &lt;br /&gt;
            dialog.monsters_tv:add_item_of_type(&amp;quot;race_node&amp;quot;)&lt;br /&gt;
        not_troll_node.race_label.label = &amp;quot;Other scary things&amp;quot;&lt;br /&gt;
        not_troll_node.race_button.visible = &amp;quot;hidden&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We define two nodes in our tree, a race_node for the top level, and a details_node for the children of a race_node.  The rest of the interesting bits are in preshow().&lt;br /&gt;
&lt;br /&gt;
We demonstrate two different ways of creating and accessing items, the first (commented out) just using the order in which they are created, while in the second we capture the result of add_item_of_type() in a variable we can use to refer to the newly defined object.  The first method is shown primarily to demonstrate the structure of the resulting objects. The second method is perhaps easier to follow, and is almost necessary when you start doing things like dynamically deleting nodes, so it is in most cases a better practice (of course, you probably won't want to use the same variable for each node like we did, and perhaps not one local to the preview function).&lt;br /&gt;
&lt;br /&gt;
We add a node, label it &amp;quot;Trolls&amp;quot;, and add a callback to the button such that when the button is checked (selected), the children of the node will be visible (the node is &amp;quot;unfolded&amp;quot;, a boolean value which defaults to false).  Then we add three nodes as children of this node.  &lt;br /&gt;
&lt;br /&gt;
Our second node, &amp;quot;Other scary things&amp;quot; will remain empty for now, so we'll set the visible attribute on its button to &amp;quot;hidden&amp;quot; (which is like false, but with hidden the widget still takes up space).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| This example is rather ugly, both in the hardwired code and the appearance of the resulting GUI, but it addresses a couple important aspects of how tree views work and how we might use them.  Let's clean it up a bit.  We'll add an indentation_step_size to the tree view, along with a spacer and [[#Alignment|horizontal_alignment]] to our details node, to make the labels line up nicely, and change the button [[#Definitions|definition]] to replace the checkbox with something that looks like it belongs there.  We will look at methods for handling layout in more depth [[#Appearance|later]].&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic tree view2c.png|center|thumb|Our tree_view with proper alignment]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local tree_view = wml.tag.tree_view {&lt;br /&gt;
    id = &amp;quot;monsters_tv&amp;quot;,&lt;br /&gt;
    indentation_step_size = 20,&lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;race_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.toggle_button {&lt;br /&gt;
                        id = &amp;quot;race_button&amp;quot;,&lt;br /&gt;
                        definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },           &lt;br /&gt;
                wml.tag.column {                                                               &lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,                                                           &lt;br /&gt;
                    wml.tag.label {                                                                                &lt;br /&gt;
                        id = &amp;quot;race_label&amp;quot;,&lt;br /&gt;
                    }                                                                                              &lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },   &lt;br /&gt;
    wml.tag.node {&lt;br /&gt;
        id = &amp;quot;details_node&amp;quot;,&lt;br /&gt;
        wml.tag.node_definition {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.spacer { width = 40 }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                    grow_factor = 1,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_type&amp;quot;,&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Multi_page===&lt;br /&gt;
====Simple Multi_page====&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
Like a tree_view, a multi_page is a heterogeneous container which is dynamically populated, however, while a multi_page contains multiple elements (pages), only one page is displayed at any one time.  Its purpose is perhaps best described by a couple of examples.&lt;br /&gt;
|-&lt;br /&gt;
[[File:Basic multipage.png|center|thumb|Multi_page showing active page]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_multipage()&lt;br /&gt;
    local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Bob&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll whelp&amp;quot;,&lt;br /&gt;
            name = &amp;quot;Junior&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A troll shaman&amp;quot;,&lt;br /&gt;
            name = _&amp;quot;Alice&amp;quot;, type = &amp;quot;Trolls&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;,&lt;br /&gt;
            label = &amp;quot;A cuttlefish&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Seamonsters&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;,&lt;br /&gt;
            type = &amp;quot;Coolers&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
                wml.tag.row {&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                            id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                        }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                         wml.tag.image {&lt;br /&gt;
                             id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                         }&lt;br /&gt;
                    },&lt;br /&gt;
                    wml.tag.column {&lt;br /&gt;
                        wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         },&lt;br /&gt;
         wml.tag.page_definition {&lt;br /&gt;
             id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
             wml.tag.row {&lt;br /&gt;
                 wml.tag.column {&lt;br /&gt;
                     wml.tag.image {&lt;br /&gt;
                         id = &amp;quot;monster_image&amp;quot;,&lt;br /&gt;
                         linked_group = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                     }&lt;br /&gt;
                 },&lt;br /&gt;
             wml.tag.column {&lt;br /&gt;
                 wml.tag.label {&lt;br /&gt;
                     id = &amp;quot;monster_label&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    multi_page&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
         for i, monster in ipairs(monsters) do&lt;br /&gt;
             if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                 dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
             else&lt;br /&gt;
                 dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
             end&lt;br /&gt;
                 dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
                 dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
         end&lt;br /&gt;
        --dialog.monsters_mp.selected_index = 5&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the code for our basic multi_page GUI looks a lot like our basic tree_view GUI.  The difference is what is displayed.  While both the tree_view and the multi_page containers contain five items, with the multi_page, only the first one is displayed.  More specifically, only the page associated with the selected_index attribute of the multi_page object, which defaults to 1, is displayed.  If we were to uncomment the last line in preshow(), we would still see only one item, but it would be the fifth one we allocated.  It's nice to know all our pages are in there somewhere, but this example is pretty useless.  What we need is a way to select which page we want to see from within our GUI.&lt;br /&gt;
&lt;br /&gt;
====A More Useful Multi_page====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| &lt;br /&gt;
|  colspan=&amp;quot;2&amp;quot; | To demonstrate the usefulness of a multi_page, and highlight its difference from a tree_view, we'll add a listbox to allow us to select the page to view.  We'll also need to add a little action to our GUI.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;align:centered&amp;quot; |[[File:More useful multipage.png|center|thumb|User selected Troll]] || [[File:More useful multipage2.png|center|thumb|User selected Cuttlefish]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function more_useful_multi_page() &lt;br /&gt;
   local monsters = {&lt;br /&gt;
        { image = &amp;quot;units/trolls/grunt.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll&amp;quot;, name = _&amp;quot;Bob&amp;quot;, &lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your uncle&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/whelp.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll whelp&amp;quot;, name = &amp;quot;Junior&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your nephew&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/trolls/shaman.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A troll shaman&amp;quot;, name = _&amp;quot;Alice&amp;quot;,&lt;br /&gt;
          race = &amp;quot;Trolls&amp;quot;, tip = &amp;quot;Your auntie&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/cuttlefish.png&amp;quot;, &lt;br /&gt;
          label = &amp;quot;A cuttlefish&amp;quot;, race = &amp;quot;Seamonsters&amp;quot;,&lt;br /&gt;
          tip = &amp;quot;Not a fish&amp;quot; },&lt;br /&gt;
        { image = &amp;quot;units/monsters/yeti.png&amp;quot;, &lt;br /&gt;
            label = &amp;quot;A yeti&amp;quot;, race = &amp;quot;Coolers&amp;quot;, &lt;br /&gt;
            tip = &amp;quot;&amp;lt;span size='large' weight='bold'&amp;gt;ROAR!&amp;lt;/span&amp;gt;&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;monsters&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = wml.tag.grid {&lt;br /&gt;
        wml.tag.row {&lt;br /&gt;
            wml.tag.column {&lt;br /&gt;
                wml.tag.image {&lt;br /&gt;
                    id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
   local listboxDefinition = wml.tag.listbox { &lt;br /&gt;
       id = listbox_id,&lt;br /&gt;
       wml.tag.list_definition {&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   wml.tag.toggle_panel {&lt;br /&gt;
                       listboxItem&lt;br /&gt;
                   }&lt;br /&gt;
               }&lt;br /&gt;
           }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local multi_page = wml.tag.multi_page {&lt;br /&gt;
        id = &amp;quot;monsters_mp&amp;quot;,&lt;br /&gt;
        wml.tag.page_definition { &lt;br /&gt;
            id = &amp;quot;trolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_name&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.page_definition {&lt;br /&gt;
            id = &amp;quot;nottrolls_page&amp;quot;,&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        id = &amp;quot;monster_image&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        id = &amp;quot;monster_label&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. _&amp;quot;Here there be &amp;quot; ..&lt;br /&gt;
                            &amp;quot;&amp;lt;span color='yellow'&amp;gt;&amp;quot; ..&lt;br /&gt;
                            _&amp;quot;MONSTERS!&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                listboxDefinition&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer {&lt;br /&gt;
                                    width = 30&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                multi_page&lt;br /&gt;
                            },&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {  -- An &amp;quot;OK&amp;quot; button&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    },&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
   local function preshow(dialog)  -- Prepare the GUI before display&lt;br /&gt;
       local listbox = dialog[listbox_id]&lt;br /&gt;
       for i, monster in ipairs(monsters) do&lt;br /&gt;
            listbox[i].monster_image.label = monster.image&lt;br /&gt;
            listbox[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            if monster.type == &amp;quot;Trolls&amp;quot; then&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;trolls_page&amp;quot;)&lt;br /&gt;
                dialog.monsters_mp[i].monster_name.label = monster.name&lt;br /&gt;
            else&lt;br /&gt;
                dialog.monsters_mp:add_item_of_type(&amp;quot;nottrolls_page&amp;quot;)&lt;br /&gt;
            end&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.label = monster.image&lt;br /&gt;
            dialog.monsters_mp[i].monster_image.tooltip = monster.tip&lt;br /&gt;
            dialog.monsters_mp[i].monster_label.label = monster.label&lt;br /&gt;
        end&lt;br /&gt;
        local function switch_page()&lt;br /&gt;
           dialog.monsters_mp.selected_index = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        listbox.on_modified = switch_page&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of this should look pretty familiar.  We've simply taken the previous example and added a second column to our GUI using code from an earlier example to add a listbox.  In addition, we altered the page layout slightly, and added a spacer column in the dialog definition to approve the appearance.&lt;br /&gt;
&lt;br /&gt;
The interesting stuff is in preshow().  Again we've merged in some listbox code from an earlier example, but we've also created a new local function switch_page(), which simply sets the selected_index attribute of our multi_page to the same as that of our listbox, and then we've configured the listbox.on_modified callback to call switch_page().  Now when the user selects an item in the listbox (updating listbox.selected_index and triggering listbox.on_modified), dialog.monsters_mp.selected_index is updated accordingly and therefore the visible page changes to the one associated with the selected unit.&lt;br /&gt;
&lt;br /&gt;
Also note in preshow() we've added a new child to our monster_image identifier for both the listbox and the multi_page, a tooltip.  When the user hovers the mouse over the image of one of our monsters, they'll see a popup message which we've added to our monster table.  Try changing '''wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; }''' to '''wml.tag.tooltip { id = &amp;quot;tooltip }''' in the dialogDefinition to see a different tooltip style.&lt;br /&gt;
&lt;br /&gt;
==Actions Have Consequences==&lt;br /&gt;
&lt;br /&gt;
So far, our GUIs have only displayed some information on the screen, but at some point we're probably going to want to use a GUI to get input from the user.  In this section we will look at return values that can be assigned to a widget based upon its state, and callbacks, which are functions invoked when something happens with a widget.  As we will see, a button is a good example, as it can return a value or take an action, or both, when pressed.  Earlier we saw how the selected_index attribute of some widgets, such as the listbox, can also be used as a sort of return value.&lt;br /&gt;
&lt;br /&gt;
===Buttons===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 | In this example, we'll create a couple buttons which provide the user a choice, use a handy confirmation popup to confirm that choice, and demonstrate how we get the results back where we can put them to use.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Basic return value.png|center|thumb|There can be only one]] || [[File:Basic return value_confirm.png|center|thumb|The user selected Alice, let's confirm this critical choice]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_return_value()&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.linked_group {&lt;br /&gt;
            id = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
            fixed_height = true,&lt;br /&gt;
        },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  -- A header &lt;br /&gt;
                wml.tag.column { &lt;br /&gt;
                    border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                    border_size = 10,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        use_markup = true,&lt;br /&gt;
                        label = &amp;quot;&amp;lt;span size='large'&amp;gt;&amp;quot; .. &lt;br /&gt;
                            _&amp;quot;Which unit shall lead your army?&amp;quot; ..  &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {  -- The body of our GUI&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.grid {&lt;br /&gt;
                        wml.tag.row {&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Alice&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image { &lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/elves-wood/sylph.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                return_value = 1&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.spacer { width = 20 }&lt;br /&gt;
                            },&lt;br /&gt;
                            wml.tag.column {&lt;br /&gt;
                                wml.tag.grid {&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.label { label = &amp;quot;Bob&amp;quot; }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.image {&lt;br /&gt;
                                                linked_group = &amp;quot;leader_lg&amp;quot;,&lt;br /&gt;
                                                label = &amp;quot;units/human-loyalists/marshal.png&amp;quot;&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    },&lt;br /&gt;
                                    wml.tag.row {&lt;br /&gt;
                                        wml.tag.column {&lt;br /&gt;
                                            wml.tag.button {&lt;br /&gt;
                                                label = &amp;quot;Select&amp;quot;,&lt;br /&gt;
                                                    return_value = 2&lt;br /&gt;
                                            }&lt;br /&gt;
                                        }&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local user_chose = gui.show_dialog(dialogDefinition)&lt;br /&gt;
    local leader&lt;br /&gt;
    if user_chose == -1 then  -- User closed the dialog by hitting the Enter key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == -2 then  -- User closed the dialog by hitting the Escape key&lt;br /&gt;
        leader = nil&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if user_chose == 1 then&lt;br /&gt;
         leader = &amp;quot;Alice&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    if user_chose == 2 then&lt;br /&gt;
        leader = &amp;quot;Bob&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local confirmed_leader_choice&lt;br /&gt;
&lt;br /&gt;
    if leader ~= nil then&lt;br /&gt;
        local query = _&amp;quot;You want &amp;quot; .. leader .. _&amp;quot; as your leader?&amp;quot;&lt;br /&gt;
        confirmed_leader_choice = gui.confirm(query)&lt;br /&gt;
    end&lt;br /&gt;
 &lt;br /&gt;
    if confirmed_leader_choice then&lt;br /&gt;
         wesnoth.message(&amp;quot;Great!&amp;quot;)&lt;br /&gt;
    else&lt;br /&gt;
         wesnoth.message(&amp;quot;Fine, lead them yourself!&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we've added a couple buttons, and assigned each of them a return value.  When the user selects one of these buttons, the GUI is closed and the value of return_value is returned from gui.show_dialog().  We then use [https://wiki.wesnoth.org/LuaAPI/gui#gui.show_prompt gui.confirm()] which provides a very simple Yes/No popup and returns true or false, respectively.  Other useful functions can be found on that page which provide handy alternatives to creating your own GUI for other simple user inputs.&lt;br /&gt;
&lt;br /&gt;
The use of return_value is rather limited, as it only returns integers and can't be used with containers like listboxes.  In more complex cases we'll need to turn to callback functions which are invoked when something happens to a widget, like clicking a button or a widget's value changing.  Earlier, we saw an example of [[LuaAPI/types/widget#on_modified|widget.on_modified()]].  More examples of callbacks can be found at [[LuaAPI/types/widget#on_modified|that link]].&lt;br /&gt;
&lt;br /&gt;
===Slider and Textbox===&lt;br /&gt;
{|&lt;br /&gt;
| Here we see a couple methods of getting more dynamic input from the user, a slider and a textbox presented in one silly example.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Slider and textbox.png|center|thumb|Two ways of getting input from the user]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function scrollbar_and_textbox()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label { &lt;br /&gt;
                        label = _&amp;quot;How much gold will you pay for this old rusty sword?&amp;quot; &lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.slider {&lt;br /&gt;
                        id = &amp;quot;gold_sl&amp;quot;,&lt;br /&gt;
                        minimum_value = 0,&lt;br /&gt;
                        maximum_value = &lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold,&lt;br /&gt;
                        value = math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.text_box {&lt;br /&gt;
                        id = &amp;quot;gold_tb&amp;quot;,&lt;br /&gt;
                        --hint_text = _ &amp;quot;Enter gold here&amp;quot;,&lt;br /&gt;
                        --hint_image = &amp;quot;images/gold_pile.png&amp;quot;,&lt;br /&gt;
                        label = tostring(math.floor(&lt;br /&gt;
                            wesnoth.sides[wesnoth.current.side].gold/2))&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button {&lt;br /&gt;
                        id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local function show_input()&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You chose &amp;quot; ..&lt;br /&gt;
                dialog.gold_sl.value .. _&amp;quot; with the slider&amp;quot;)&lt;br /&gt;
            wesnoth.interface.add_chat_message(_&amp;quot;You entered &amp;quot; .. &lt;br /&gt;
                tostring(dialog.gold_tb.text) .. _&amp;quot; in the text_box&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
        -- this is a button, so we use on_button_click, not on_left_click&lt;br /&gt;
        dialog.ok.on_button_click = show_input  &lt;br /&gt;
&lt;br /&gt;
        dialog.gold_sl.on_modified = function()&lt;br /&gt;
            dialog.gold_tb.text = tostring(dialog.gold_sl.value)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We create a slider, with a range from 0 to the amount of gold possessed by the current side and an initial value in the middle, and a text box with the same initial value.  We assign a function to our OK button which simply reports on the values provided by the user.  For no reason whatsoever, we add a callback such that when the user adjusts the slider the value in the textbox is update to match the slider.&lt;br /&gt;
&lt;br /&gt;
Note that the textbox returns text, even though it looks like we're expecting the user to input a natural number.  Remember to validate those inputs.&lt;br /&gt;
&lt;br /&gt;
You can use text_hint to place a caption in the box that will help the user understand what to enter in the box, and possibly an image as well.  For example, in the search box in the recall menu uses '''hint_text = _ &amp;quot;Search&amp;quot;, hint_image = &amp;quot;icons/action/zoomdefault_25.png~FL(horiz)&amp;quot;'''.  Of course, you can't have a hint and a label in the same text_box at the same time, so in our example we've only included them as comments.&lt;br /&gt;
&lt;br /&gt;
There is also a widget called a spinner, which is kind of like the combination of a text_box and a slider.  As of the release of 1.18, it appears to be unfinished so the strange syntax needed to make it work is probably not the best thing to document, and we will omit it for now.&lt;br /&gt;
&lt;br /&gt;
==Appearance==&lt;br /&gt;
&lt;br /&gt;
'''This section needs help'''&lt;br /&gt;
&lt;br /&gt;
===Borders===&lt;br /&gt;
&lt;br /&gt;
Borders allow you to force unused space around a column, for example so that your widgets don't runtogether.  You can specify the border to be one or more of top, bottom, left, right, or all.  The border_size sets the amount of padding, in pixels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
wml.tag.column{&lt;br /&gt;
   border = &amp;quot;left, right&amp;quot;&lt;br /&gt;
   border_size = 25&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Alignment===&lt;br /&gt;
{|&lt;br /&gt;
| colspan=2 |By default, the GUI will usually center widgets in their cells, which is not always what we want.  In this example, we use horizontal_alignment to move widgets around a little.  &lt;br /&gt;
&lt;br /&gt;
In more complex cases, it may be useful to add [[GUIWidgetDefinitionWML#Spacer|spacers]] to help force alignment, or use linked_groups to force consistent alignment for objects within a grid.&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Gui tutorial alignment without.png|center|thumb|Default alignment]] ||[[File:Gui tutorial alignment with.png|center|thumb|Showing off some alignment options]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function basic_alignment()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Ralph&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/grunt.png&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            wml.tag.row {&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                    wml.tag.label {&lt;br /&gt;
                        label = &amp;quot;Sam&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.image {&lt;br /&gt;
                        label = &amp;quot;units/trolls/troll-hero-attack-se-4.png&amp;quot;  -- 122x102&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
           },&lt;br /&gt;
           wml.tag.row {&lt;br /&gt;
               wml.tag.column {&lt;br /&gt;
                   horizontal_alignment = &amp;quot;left&amp;quot;,&lt;br /&gt;
                   wml.tag.label {&lt;br /&gt;
                       label = &amp;quot;Jr&amp;quot;&lt;br /&gt;
                   }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    horizontal_alignment = &amp;quot;right&amp;quot;,&lt;br /&gt;
                        wml.tag.image {&lt;br /&gt;
                            label = &amp;quot;units/trolls/whelp.png&amp;quot;  -- 72x72&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The screenshots show the output of this example with and without the horizontal_alignment lines included above.&lt;br /&gt;
&lt;br /&gt;
A label allows you to set the text_alignment field (e.g. text_alignment = &amp;quot;left&amp;quot;).  Note, however, this only aligns the text within the label.  The label itself will probably be centered in the column, giving the false appearance that your text alignment is not working.&lt;br /&gt;
&lt;br /&gt;
===Growth===&lt;br /&gt;
&lt;br /&gt;
To keep your dialog nicely balanced, the GUI2 engine may need to grow rows and/or columns.  You can control which columns, for example, grow and which do not, by setting some with grow_factor = 1, and others with grow_factor = 0 (do not grow).  While grow factors of 0 and 1 are the most common, you can use other values to adjust the relative growth if you really need to, see [[GUILayout]] for the gory details.&lt;br /&gt;
&lt;br /&gt;
It it sometimes useful to include a column with a [spacer] and a grow_factor (often the only column with grow_factor != 0) whose sole purpose is to keep your GUI aligned nicely as the layout engine does its evil.&lt;br /&gt;
&lt;br /&gt;
To force a column to stretch to fit available space, use horizontal_grow = true.  Note that horizontal_grow is not compatible with horizontal_alignment.  There is also a vertical_grow parameter. &lt;br /&gt;
&lt;br /&gt;
If you need to see every little detail about the layout process, start wesnoth with --log-debug=gui/layout.  Good luck with that.&lt;br /&gt;
&lt;br /&gt;
===Definitions===&lt;br /&gt;
Many widgets can be configured to have to a different appearance, for example in our tree_view example we changed the definition of a toggle_button from the default of a checkbox by setting definition = &amp;quot;tree_view_node&amp;quot;.  This option was found by looking at the id of a toggle_button_definition in .../data/gui/widget/toggle_button_tree_view_node.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
#textdomain wesnoth-lib&lt;br /&gt;
###&lt;br /&gt;
### Definition of a toggle button to be used in a tree view as node fold/unfold indicator&lt;br /&gt;
###&lt;br /&gt;
[toggle_button_definition]&lt;br /&gt;
        id = &amp;quot;tree_view_node&amp;quot;   # &amp;lt;--- we can use 'definition = &amp;quot;tree_view_node&amp;quot;' in a [toggle_button] to select this definition&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node.&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|There are many other definitions for buttons and other widget types in that directory.  It would be nice to have a list (linked here), but for now you'll just have to look around.&lt;br /&gt;
&lt;br /&gt;
We can even create our own custom definitions using [[LuaAPI/gui#gui.add_widget_definition|gui.add_widget_definition()]].  In this example, we copy from .../data/gui/widget/toggle_button_tree_view_node.cfg with a slight change so that our button turns red ( '''~BLEND(255,0,0,1)''' ) when focused. &lt;br /&gt;
&lt;br /&gt;
In this example, we will use wesnoth.wml_actions to create the WML tag [add_widget_def_demo].&lt;br /&gt;
&lt;br /&gt;
Note the first line, a common convention for creating an alias for wml.tag.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial custom widget.png|center|thumb|Different definition of buttons, including one of our own (right)]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag -- save ourselves some typing&lt;br /&gt;
function wesnoth.wml_actions.add_widget_def_demo()&lt;br /&gt;
    local definition = {&lt;br /&gt;
        id = &amp;quot;tree_view_node_custom&amp;quot;,&lt;br /&gt;
        description = &amp;quot;Fold/unfold status indicator of a tree view node (MODIFIED).&amp;quot;,&lt;br /&gt;
        T.resolution {&lt;br /&gt;
            min_width = 25,&lt;br /&gt;
            min_height = 19,&lt;br /&gt;
            default_width = 25,&lt;br /&gt;
            default_height = 19,&lt;br /&gt;
            max_width = 25,&lt;br /&gt;
            max_height = 19,&lt;br /&gt;
            -- Unselected - note there's no tags for unselected/selected, that's simply determined by the order &lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/fold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            -- Selected&lt;br /&gt;
            T.state {&lt;br /&gt;
                T.enabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                         T.image { name = &amp;quot;buttons/unfold-arrow.png&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.disabled {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~GS()&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                T.focused {&lt;br /&gt;
                    T.draw {&lt;br /&gt;
                        T.image { name = &amp;quot;buttons/unfold-arrow.png~BLEND(255,0,0,1)&amp;quot; }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.add_widget_definition(&amp;quot;toggle_button&amp;quot;, &amp;quot;tree_view_node_custom&amp;quot;, definition)&lt;br /&gt;
&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.tag.toggle_button {&lt;br /&gt;
                        definition = &amp;quot;default&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.toggle_button {&lt;br /&gt;
                    definition = &amp;quot;tree_view_node&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            },&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.toggle_button {&lt;br /&gt;
                    definition = &amp;quot;tree_view_node_custom&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    gui.show_dialog(dialogDefinition)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[GUIWidgetDefinitionWML]] for more details on widget definitions.&lt;br /&gt;
&lt;br /&gt;
You can also give the whole dialog a definition, like definition = &amp;quot;tooltip_large&amp;quot;.  There is no gui.add_window_definition(), however a window is technically a type of widget so it may be possible to create your own window definitions (please update this if you do).&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
===Canvases===&lt;br /&gt;
Part of panels?  Sort of?&lt;br /&gt;
&lt;br /&gt;
A canvas is a surface you can draw on.  A dialog has them, as does a panel, and for these canvas 1 refers to the background, while canvas 2 refers to the foreground.  Other widgets may have canvases that may have other meanings, or no canvases at all.  See more at [[LuaAPI/gui/widget#set_canvas]].&lt;br /&gt;
&lt;br /&gt;
Here's a fun little trick.  Set your dialog background to be transparent:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local function preshow(dialog)&lt;br /&gt;
    dialog:set_canvas(1, { } )&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if you want an opaque GUI background with the screen behind it blurred like what you see behind the text of a [message], you can set your window definition to &amp;quot;message&amp;quot;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
definition = &amp;quot;message&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Here we take our [[#Progress Bar|progress bar]], and add a text overlay.&lt;br /&gt;
&lt;br /&gt;
Note: either using text on a canvas is rather limited, or I just couldn't figure it out.  For example, I could not get the text size any smaller, and any attempts to do so simply resulted in very blocky text.  And the spaces were necessary so that the text wasn't stretched out.  I also find it surprising that the progress bar does not have this feature inherently.  So it's not a great example, but it should be enough to get you started using canvases.  Be sure to visit the [[LuaAPI/gui/widget#set_canvas|link]] mentioned above for more options.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial canvas text.png|center|thumb|A progress bar in the background, with text in the foreground]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar_with_overlay()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.grid { &lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.panel { id = &amp;quot;panel&amp;quot;,&lt;br /&gt;
                        T.grid {&lt;br /&gt;
                            T.row {  &lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                                        label =_ &amp;quot;Press me&amp;quot;}&lt;br /&gt;
                                    },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                                },&lt;br /&gt;
                                T.column {&lt;br /&gt;
                                    T.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                                    label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                                    }&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                } &lt;br /&gt;
            }&lt;br /&gt;
        } &lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        dialog.panel:set_canvas(2, { T.text { text_alignment = &amp;quot;center&amp;quot;, font_size = 48,&lt;br /&gt;
             text_markup = true, text = &amp;quot;&amp;lt;span color='yellow'&amp;gt;                            &amp;quot; ..     &lt;br /&gt;
             dialog.progress.percentage .. &amp;quot;%                            &amp;lt;/span&amp;gt;&amp;quot; } } ) &lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
             dialog.button.enabled = false&lt;br /&gt;
             dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice we added a panel and placed our text on the foreground canvas(2) on it, since the progress_bar itself does not support canvases.&lt;br /&gt;
&lt;br /&gt;
===Placement===&lt;br /&gt;
&lt;br /&gt;
You may have noticed that all of our dialogs are centered on the screen.  This is the default.  You can override this and place the dialog wherever you like by setting automatic_placement = false, along with x, y, width, and height at the top level of your dialog definition (next to tooltip =, etc).  &lt;br /&gt;
&lt;br /&gt;
'''This part about placement needs review'''&lt;br /&gt;
If you prefer, you may replace x and/or y with horizontal_placement and vertical_placement, such as horizontal_placement = &amp;quot;left&amp;quot;.  You can even set the placement values using WFL, for example horizontal_placement = &amp;quot;(gamemap_width / 3)&amp;quot; -- see [[#Using WFL with GUI2|Using WFL with GUI2]].&lt;br /&gt;
&lt;br /&gt;
==Miscellaneous==&lt;br /&gt;
&lt;br /&gt;
TODO:  This stuff doesn't belong in a tutorial.  It's worth documenting, but not here.  Better to save these here for now than keep them on my laptop.&lt;br /&gt;
&lt;br /&gt;
===Progress Bar===&lt;br /&gt;
{|&lt;br /&gt;
|A progress_bar is a graphical representation of a percent.  In this example, we present the user with a puzzle.  They must hit the button repeatedly before they can close the GUI.  A progress_bar displays their current progress toward completion.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial progress bar.png|center|thumb|upright=2]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
function wesnoth.wml_actions.progress_bar()&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        wml.tag.tooltip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.helptip { id = &amp;quot;tooltip_large&amp;quot; },&lt;br /&gt;
        wml.tag.grid {&lt;br /&gt;
            wml.tag.row {  &lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;button&amp;quot;,&lt;br /&gt;
                        label =_ &amp;quot;Press me&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.progress_bar { id = &amp;quot;progress&amp;quot; }&lt;br /&gt;
                },&lt;br /&gt;
                wml.tag.column {&lt;br /&gt;
                    wml.tag.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                        label = _&amp;quot;Done&amp;quot;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        dialog.ok.enabled = false&lt;br /&gt;
        dialog.button.on_button_click = function() &lt;br /&gt;
        dialog.progress.percentage = dialog.progress.percentage + 10&lt;br /&gt;
        if dialog.progress.percentage &amp;gt; 99 then&lt;br /&gt;
            dialog.button.enabled = false&lt;br /&gt;
            dialog.ok.enabled = true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Unit Preview Pane===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|A unit_preview_pane takes a unit (or a unit type), and presents a graphical representation of the unit and its more important attributes, along with tooltips for additional details, in the same way that the recall menu does.  Here we see an example of a unit which has picked up some items, including a weapon, which are affecting its stats.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Gui tutorial unit preview pane.png|center|thumb]]&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=lua&amp;gt;&lt;br /&gt;
local T = wml.tag&lt;br /&gt;
&lt;br /&gt;
function wesnoth.wml_actions.recall_from_variable(cfg)&lt;br /&gt;
    local from_array = cfg.from or wml.error(&lt;br /&gt;
        &amp;quot;[recall_from_variable]: missing required from= &amp;quot;)&lt;br /&gt;
    local to_var = cfg.to or wml.error(&lt;br /&gt;
       &amp;quot;[recall_from_variable]: missing required to= &amp;quot;)&lt;br /&gt;
    local unit_list = wml.array_access.get(from_array) or wml.error(&lt;br /&gt;
        string.format(&amp;quot;[recall_from_variable]: failed to fetch wml array %s&amp;quot;,from_array))&lt;br /&gt;
&lt;br /&gt;
    local listboxItem = T.grid {&lt;br /&gt;
        T.row {&lt;br /&gt;
            T.column {&lt;br /&gt;
                T.label { id = &amp;quot;available_unit&amp;quot;,&lt;br /&gt;
                     linked_group = &amp;quot;available_unit&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local listbox_id = &amp;quot;available_units&amp;quot;&lt;br /&gt;
    local listboxDefinition = T.listbox { id = listbox_id,&lt;br /&gt;
        T.list_definition {&lt;br /&gt;
            T.row {&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.toggle_panel { listboxItem }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    local dialogDefinition = {&lt;br /&gt;
        T.tooltip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.helptip { id = &amp;quot;tooltip&amp;quot; },&lt;br /&gt;
        T.linked_group { id = &amp;quot;available_unit&amp;quot;, fixed_width = true },&lt;br /&gt;
        T.grid {&lt;br /&gt;
            T.row {  -- header&lt;br /&gt;
                T.column {&lt;br /&gt;
                    T.grid {&lt;br /&gt;
                        T.row {&lt;br /&gt;
                            T.column {&lt;br /&gt;
                                border = &amp;quot;bottom&amp;quot;,&lt;br /&gt;
                                border_size = 10,&lt;br /&gt;
                                T.label {&lt;br /&gt;
                                    use_markup = true,&lt;br /&gt;
                                    label = &amp;quot;&amp;lt;span size='large' color='yellow' weight='bold'&amp;gt;&amp;quot;&lt;br /&gt;
                                        .. _&amp;quot;Select unit to recall&amp;quot; .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                                }&lt;br /&gt;
                            }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Body&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;right&amp;quot;,&lt;br /&gt;
                                 border_size = 40,&lt;br /&gt;
                                 listboxDefinition&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 T.unit_preview_pane { id = &amp;quot;unit_preview&amp;quot; }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             },&lt;br /&gt;
             T.row {  -- Footer&lt;br /&gt;
                 T.column {&lt;br /&gt;
                     T.grid {&lt;br /&gt;
                         T.row {&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                  T.spacer { width = 400 }&lt;br /&gt;
                             },&lt;br /&gt;
                             T.column {&lt;br /&gt;
                                 border = &amp;quot;top,right&amp;quot;,&lt;br /&gt;
                                 border_size = 10,&lt;br /&gt;
                                 T.button { id = &amp;quot;ok&amp;quot;,&lt;br /&gt;
                                     label = _&amp;quot;OK&amp;quot;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local picked = 1&lt;br /&gt;
&lt;br /&gt;
    local function preshow(dialog)&lt;br /&gt;
        local listbox = dialog[listbox_id]&lt;br /&gt;
            for i,unit in ipairs(unit_list) do&lt;br /&gt;
                listbox[i].available_unit.label = unit.name .. &amp;quot;(&amp;quot; .. &lt;br /&gt;
                    unit.language_name .. &amp;quot;)&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
        local function draw_unit()&lt;br /&gt;
            wesnoth.units.to_recall(unit_list[listbox.selected_index])&lt;br /&gt;
            local tmp = wesnoth.units.find_on_recall{ id = &lt;br /&gt;
                unit_list[listbox.selected_index].id }[1]&lt;br /&gt;
            dialog.unit_preview.unit = tmp&lt;br /&gt;
            wesnoth.units.extract(tmp)&lt;br /&gt;
            picked = listbox.selected_index&lt;br /&gt;
        end&lt;br /&gt;
        draw_unit()&lt;br /&gt;
        listbox.on_modified = draw_unit&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    gui.show_dialog(dialogDefinition,preshow)&lt;br /&gt;
&lt;br /&gt;
    wml.variables[to_var] = picked - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should all be pretty self evident by now.  We are provided with an array of stored units (from [store_unit] in WML).  We create a listbox populated with units and we use the selected_index to determine which element in the table to send to unit_preview_pane.  Since our input is an array of unit data, not actual units, we use [[LuaAPI/wesnoth/units#wesnoth.units.to_recall|wesnoth.units.to_recall]] to take the definition of one from our array and place it on the recall list (turning it into an actual unit), [[LuaAPI/wesnoth/units#wesnoth.units.find_on_recall|wesnoth.units.find_on_recall]] to fetch that unit in a form that the unit_preview_panel understands, and finally [[wesnoth.units.extract|wesnoth.units.extract]] to remove the unit from the recall list when we are done with it.&lt;br /&gt;
&lt;br /&gt;
And of course we subtract one from the selected_index when we return our choice to WML, since lua arrays count from 1 and WML from 0.&lt;br /&gt;
&lt;br /&gt;
The unit_preview_pane will also accept a unit_type instead of a specific unit.&lt;br /&gt;
&lt;br /&gt;
==Appendix==&lt;br /&gt;
&lt;br /&gt;
===Explore Your Options===&lt;br /&gt;
&lt;br /&gt;
We've seen a lot of options that can be set to modify the behaviour of our dialogs, some on columns, some on widgets, etc.  These are in the process of being documented [[GUIWidgetInstanceWML|here]], but if you would like to go straight to the source, the data Wesnoth uses to validate your configuration can be found in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui   data/schema/gui] under your install directory.&lt;br /&gt;
&lt;br /&gt;
Let's look at a scroll_label, for example.  A scroll_label is a widget, so we look in [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/widget_instances.cfg   widget_instances.cfg] and find the following.  Here we can see five parameters we can provide to our scroll_label (in addition to the ones available to all widgets, like id and definition, see the entry super=... which refers you to the widget_instance in the file [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/generic.cfg data/schema/gui/generic.cfg]), along with their types and default values.  For example, we could set &amp;quot;link_aware = true&amp;quot;, and if we do not we can assume that link_aware will be false.  While this does not explain what these parameters do, the information provided in the schema directory is often helpful nonetheless.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
    [tag]&lt;br /&gt;
        name=&amp;quot;scroll_label&amp;quot;&lt;br /&gt;
        min=&amp;quot;0&amp;quot;&lt;br /&gt;
        max=&amp;quot;infinite&amp;quot;&lt;br /&gt;
        super=&amp;quot;$generic/widget_instance&amp;quot;&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;horizontal_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;vertical_scrollbar_mode&amp;quot; scrollbar_mode initial_auto}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;wrap&amp;quot; bool true}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;text_alignment&amp;quot; f_h_align &amp;quot;left&amp;quot;}&lt;br /&gt;
        {DEFAULT_KEY &amp;quot;link_aware&amp;quot; bool false}&lt;br /&gt;
    [/tag]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that our scrollbars are of type scrollbar_mode.  It would probably help if we knew what values are available to the scrollbar_mode.  In [https://github.com/wesnoth/wesnoth/tree/master/data/schema/types/gui.cfg   data/schema/types/gui.cfg] we find this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=wml&amp;gt;&lt;br /&gt;
[type]&lt;br /&gt;
    name=scrollbar_mode&lt;br /&gt;
    value=&amp;quot;always|never|auto|initial_auto&amp;quot;&lt;br /&gt;
[/type]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The variable types found in the schema files are described at [[GUIVariable]].&lt;br /&gt;
&lt;br /&gt;
===Using WFL with GUI2===&lt;br /&gt;
&lt;br /&gt;
If you look at the variable type descriptions at [[GUIVariable]] you may notice that many of them start with &amp;quot;f_&amp;quot; and have &amp;quot;or formula&amp;quot; in the description.  This means that you can use [[Wesnoth_Formula_Language|Wesnoth Formula Language (WFL)]] formulas in these fields, with certain variables made available to you (which variables and what they mean can be challenging to ascertain, but you can generally figure it out by example).  &lt;br /&gt;
&lt;br /&gt;
Looking at [https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui/window.cfg data/schema/gui/window.cfg] we see that 'height' has type f_unsigned, which tells us that height is an unsigned integer, and that we can use a WFL formula to define it in a window_definition.  In [https://github.com/wesnoth/wesnoth/tree/master/data/gui/themes/default/window/wml_message.cfg data/gui/window/wml_message.cfg] (data/gui/themes/default/window/wml_message.cfg starting around 1.19.2), we find the line '''height = &amp;quot;(screen_height - 30)&amp;quot;'''.  This does exactly what it looks like, it sets the height of our window to 30 pixels less than the height of the screen.&lt;br /&gt;
&lt;br /&gt;
===Useful Links===&lt;br /&gt;
&lt;br /&gt;
[[LuaAPI/gui|LuaAPI/gui - Mostly about opening windows]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[LuaAPI/types/widget|LuaAPI/types/widget - Widget attributes and callbacks]]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://wiki.wesnoth.org/Category:GUI_WML_Reference  GUI_WML_Reference]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://github.com/wesnoth/wesnoth/tree/master/data/schema/gui .../data/schema/gui/*.cfg] - Lists of valid options for various GUI objects&amp;lt;br&amp;gt;&lt;br /&gt;
[https://devdocs.wesnoth.org/layout_algorithm.html Layout Algorithm] - For windows, at least&lt;br /&gt;
&lt;br /&gt;
===Credits===&lt;br /&gt;
&lt;br /&gt;
The basic framework that composes the initial examples was lifted from LotI.  It's a great place to find well written examples, but some of it is complex enough to be a little overwhelming when getting started.&lt;br /&gt;
&lt;br /&gt;
Many examples, particularly tree view and multipage, are heavily derived from the World Conquest multiplayer campaign.&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.wesnoth.org/index.php?title=LotI_Walkthrough-Part1-Chapter03&amp;diff=73558</id>
		<title>LotI Walkthrough-Part1-Chapter03</title>
		<link rel="alternate" type="text/html" href="https://wiki.wesnoth.org/index.php?title=LotI_Walkthrough-Part1-Chapter03&amp;diff=73558"/>
		<updated>2024-08-24T09:47:49Z</updated>

		<summary type="html">&lt;p&gt;White haired uncle: /* Darkest Darkness */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Part I, Embracing the Darkness, Chapter 3, Shadows of the Night'''&lt;br /&gt;
&lt;br /&gt;
'''Generally'''&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Recruiting and recalling work differently than normal in this chapter.  Be sure to read and understand the introductory material at the beginning of the first scenario.  Villages will often provide no income, check the status table (Alt-s, then Scenario Settings) at the start of each scenario.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' In a nutshell, recruiting is 10x normal cost, but units are automatically recalled, are loyal, and advance slightly faster. Units can be normally recalled, but you will start some scenarios without a keep so you can't rely on this. Don’t forget about using gems and items on units on the recall list.&lt;br /&gt;
&lt;br /&gt;
==Thirst for Adventures==&lt;br /&gt;
'''[WHU]''' Recruits are not really necessary here, and if Efraim and Lethalia are fast, they'll just slow you down.  If you do recruit, keep them back and have Lethalia and Efraim protect them from the first batch of wolves and mists.  The town &amp;quot;to the east&amp;quot; is actually to southeast, the first time the road forks follow the southeast branch with your fastest leader.  North of the town is a swamp, kill the lich.  You will be given the opportunity to go on an optional scenario, why not?&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' The mists and wolves have gotten much harder at the start. Even a group of L3-L4 recalls can have some problems with them and even Lethalia can get killed. L1 recruits will just get mopped up. Note if you recall there are a lot of villages, but you cannot get positive income, only zero. There is however no time limit, so you can recruit, get a bunch of villages and then recall. You do want to carry over some gold to the next level, especially if you choose to fight the bandits. Note there is an enemy bandit leader at 62,63 (south central) who makes for a good fight for L1 recruits. He is only triggered when you get close to him. The enemy lich also apparently recruits without end and doesn't attack, so you can harvest XP form his recruits until you get bored.&lt;br /&gt;
&lt;br /&gt;
==Bandits (Optional Scenario)==&lt;br /&gt;
'''[WHU]'''  Recruit a couple elves, give/craft them some gear, and try to get them some experience.  Use heroes to block enemies to protect your new elves, and Argan to provide leadership.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Note villages provide income and there is 100% gold carry over. If present, Beelzebub's monument will be at 16,17.&lt;br /&gt;
&lt;br /&gt;
==Journey South==&lt;br /&gt;
'''[WHU]''' A long scenario, without much opportunity to use low level units.  About ten tiles southeast of the mouth of the path through the mountains is a small orc camp.  You may want to send a few heroes over the mountains to take it out.  I've always chosen to help the woman which gives a nice reward, but I don't know what the other options do.  After you enter the cave, there is a lake full of souls to eat.  On the west side of the lake is a chest of gold.  One leader can easily clear the path on land of the enemy undead.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Following the path south you find a cavern.  There are trolls to the west, which provide what IMO is one of the toughest fights in LotI unless you can get to the opening where you fight two on one in your favor.  It's no place for your junior units, they can safely remain heading south.  Fighting the trolls is not strictly necessary if you just keep moving south.  If you choose to go west, look for the entrance to a secret passage to the south, there's a piece of loot in there that is weakly protected.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Shortly after exiting the cave there is a gap in the mountains to the west which leads to a path to a secret scenario.  It is quite difficult, but doable and gives you access to some dwarves, which is nice, especially if you're building up a collection of axes.  If you chose not to fight the trolls and only sent a unit or two through the secret passage, this might be their only hope of survival (unless you sent Lethalia alone, who can fly to a tile inaccessible to the trolls).  The alternative is just to cruise easily down to the southern border.  Either way you should finish at least 100 turns early -- with no early finish bonus.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Only things to add to WHU's notes: If you take the female necromancer's side such that she is an ally and then you fight Beelezebub, you can run into issues with her units sitting on items resulting from Beelezebub's death. There is 200 gold hidden in cave in 2nd mountain range to the east, north of female necromancer; it's easiest to get to from the south side of the range. Income from villages can only bring you to zero income, not take you positive.&lt;br /&gt;
&lt;br /&gt;
==Mining (Optional Scenario)==&lt;br /&gt;
'''[WHU]''' Time to recall or possibly recruit some units.  The turn limit is very tight here if you don't have overwhelming force.  Your enemies, aside from the four liches, are weak, but you have a lot of work to do and a lot of map to cover so you want plenty of troops to clear the way for your heroes.  In the northeast you'll be facing goblins, Lethalia and some elf markmen should have no trouble there.  The rest will be undead, so arcane and impact attacks are key.  While you are in a cave, most of the paths are covered with roads.  This is a good scenario to get some XP for lower level units.  Spread your forces so that you are advancing along all paths at once, and try to make sure your heroes move as much as possible each turn, while still blocking enemy units from teaming up on your low level units.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' You can recruit dwarven fighters now, though the ones you start with will be auto-recalled in future scenarios, so it's worth putting effort into advancing them. I found with some care, you can handle this scenario without recruiting but recalling a healer or two is helpful. You will need to keep an eye on the turn limit.&lt;br /&gt;
&lt;br /&gt;
==Siege==&lt;br /&gt;
'''[WHU]''' Gold, or XP?  A fast leader can race down and get behind the orc leader, step into his castle, and win around turn 4, picking up a nice early finish bonus, but leaving a lot of XP on the table.  On the other hand, your allies are actually useful, so you could join them in a straight up assault and grab a lot of XP.  Your allies have healers you can take advantage of by carefully positioning your units.  &lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' I like a hybrid approach, where I send a few heroes to stand in the orc castle so he can't recruit very fast and then pick them off a few at a time.  You don't get much gold that way, but it's safe, especially if you want to distribute XP to junior units, at least until your ally joins you in the castle.  I don't think this is a very wise approach, but it's fun, especially if you mix in some explosive slow attacks to really frustrate the orcs.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' If you do decide to harvest XP, your biggest challenge will be your ally stealing kills from you.&lt;br /&gt;
&lt;br /&gt;
==Entering the Desert==&lt;br /&gt;
'''[WHU]''' Recruit a few mages, protect them, and take advantage of Argan's leadership and Stormrider's burn foes to help the mages advance.  Send a couple elves to scout the forest for villages.  Send your army south, following the road.  Efraim and Lethalia are relatively safe to explore the desert, but watch out for the occasional enemy that petrifies.  There are a lot of enemies with poison, so lead with your undead.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' In the southeast corner is a pit that will spawn ghostly units in increasing number.  The idea here is to use those ghosts as target practice for your mages.  I just don't find that practical, it's very difficult to protect them.  I go for the big early finish bonus.  Whichever you choose, Lethalia (or Efraim if you have advanced his movement AMLAs to at least the levitate upgrade) should be making constant movement toward the pit, as the ghosts will surround your leader on every turn.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' You can get away without recruiting/recalling, but it is a good chance to harvest some XP. The enemies with the petrify attack are nearly invisible, so keep a close eye out for them. Petrify doesn’t seem to be curable except by potion? There are two items in SW part of map.&lt;br /&gt;
&lt;br /&gt;
==The Pit==&lt;br /&gt;
'''[WHU]'''  Send a quick dwarf or other unit that moves well in caves along the north border to pick up an item in the northeast corner.  Send your heroes southeast to find the glyph where the ghosts spawn and step on it to stop them.  You can leave your low level and/or slow units behind, they won't be much use against the units you'll be up against.  If you do decide to bring them, use Efraim and Lethalia together to disable the glyph, keeping ghosts in front of you for the most part, while Delly, Argan, and Stormrider protect the rest of the army from any ghosts that get by.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Continue following the path around the glyph until you encounter the next batch of enemies, which may not be the most dangerous you have faced so far, but certainly close.  Use the bridge and rotate back to heal/regenerate as necessary until you get the upper hand, then charge forward.  If you have given Stormrider a lot of HP and defenses and upgraded his burns foes, he can be a valuable tool on the front line here.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Nothing to add.&lt;br /&gt;
&lt;br /&gt;
==Darkest Darkness==&lt;br /&gt;
'''[WHU]''' This one can be a little tricky.  You have to protect your troops from higher level ghosts sneaking in from all directions, but you also need to be using your stronger units to quickly hunt down the enemy leaders (north, northeast, northwest, and southeast).&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' The toughest leader is to the NE. There are escape tunnels in the SW and SE that end the scenario.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' I never noticed that the objectives say that escape is also an option.  There is only one tunnel that leads to escape, however, in the SW.&lt;br /&gt;
&lt;br /&gt;
==End of all Hopes==&lt;br /&gt;
'''[WHU]''' Efraim and Lethalia, working together, can accomplish the main mission, though it helps to remember that is to escape and not to waste time with the enemy leader.  Send everyone but Efraim and Lethalia north, and defend the one tile gap, keeping the undead trapped underground.  Watch out for chocobone charges.  You can also send some units into the narrow passages in the southeast if you want to spread the XP around, just make sure to have some healers and leave enough room to rotate troops back to heal.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Use Efraim and Lethalia to draw the bulk of the undead to the northern part of the underground, then race around to the south and west, waiting near the exit until the orc leader goes down, which will allow you access to cheap bandit recruits.  Or draw the undead to the northern part of the underground while sending a unit with lesser nightstalk ([[LotI_Items#Nighwalker_.E2.80.93_craftable_as_any_armour|Nighwalker]]) and darkens ([[LotI_Items#Deflector_of_Light_.E2.80.93_craftable_as_any_armour|Deflector of Light]]) to sneak to the exit.  There is no early finish bonus, so you may want to milk some XP at the end.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' No income from villages. If you kill the orcish leader outside, you will gain the ability to recruit chaotic human units. I split my troops, sending the elves outside along with Stormrider, the dwarves west, and split my mages as most useful. Good time to consider recruiting/recalling some low-level mages.&lt;br /&gt;
&lt;br /&gt;
==Lost==&lt;br /&gt;
'''[WHU]''' Send Efraim and Lethalia south and take out the drakes just for being drakes.  Then head west and turn south to kill a dragon and pick up a new toy.  I used to think Efraim should take it, but I now prefer to give it to Lethalia.  Head back north, turn west.  In the southwest will be a bunch of goblins.  North from there on the western edge of the map about halfway up is the exit.  There's no early finish bonus, so you may want to explore areas to the north.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Meanwhile, you can move the rest of your army generally southwest.  There will be a detour heading north, but just keep aiming south and west as best you can.  You should meet up with Efraim and Lethalia shortly before they reach the goblins, which can be used as XP for lower level units or to run up your soul eater count for Efraim and/or Lethalia.  Alternatively, you could use your army to explore north, or just leave them at the start, Efraim and Lethalia can easily finish this scenario in about 50 turns by themselves.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' No income from villages. Your four main heroes are basically invincible, so you can split into four groups with a hero leading each and effectively divide and conquer this scenario. Send some fliers north to fight the bats and kill the bat leader in the NE. The big room to the SE seems to be empty.&lt;br /&gt;
&lt;br /&gt;
==Ambush==&lt;br /&gt;
'''[WHU]''' There are a couple ways to get through this scenario without losing units.  My choice depends on how my units are initially positioned, what strengths and weaknesses my army has, and which and how many potions I have in my inventory.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Option one, move any junior units you aren't will to sacrifice to the center and hold a solid formation.  This assumes you have good defensive units and a handful of healing potions.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Option two, pick a direction, clear it with your heroes, and run for it so you can shield your junior units mostly with terrain and keep the fight away from them.  Hit and run, or greater healing potions will probably be necessary here, so your heroes can attack and then assume defensive position.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' If neither of these options are available, and you can't come up with an alternative, you could always remove any gear you care about from some expendable units and position them to slow the enemy.  They'll almost certainly die on the first turn, but the units that kill them will have to expend their turn to kill them.  Immediately go on offense with your heroes.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' The biggest threat is the necromancers, try to kill them before they attack while tolerating other enemies.&lt;br /&gt;
&lt;br /&gt;
==Gehenna==&lt;br /&gt;
'''[WHU]''' First you need to defend against a short wave of relatively powerful enemies.  Lethalia can easily defend the southern entrance, backed by a couple junior units who are just there to pick up an easy kill or two when available.  The northern entrance will probably require the rest of your heroes and a few senior units to rotate in and out.  The initial defense (in the north at least) is more challenging than most of what you have encountered so far, but it isn't really difficult if you keep a good defensive line so an individual unit doesn't get ganged up on and rotate the front line out to heal.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' After the initial assault has been beaten back, pick a leader to send to the northwest corner of the map where there is a bunch of loot.  Send the rest of your heroes, split into a couple teams, to the west.  You will meet light resistance until you approach the perimeter of the enemy defenses.  Punch a hole through the front line, and relentlessly move forward.  The leader looting the treasury should be starting to fight southward.  The rest of your army will be relatively safe back at the castle, just expect a few bats to drop by.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' When you see the enemy leader, check his resistances (click on the unit, mouse over the HP values on the right side of the screen).  He is easy to kill, but only if you hit him with the right attacks.  There's no early finish bonus, so once you reach him you may want to spend some time killing his underlings.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Beelzebub's monument will be at 10,9 if present.&lt;br /&gt;
&lt;br /&gt;
==Achilles' Revenge==&lt;br /&gt;
'''[WHU]''' Still have that [[LotI_Items#Woodland_Cloak_.E2.80.93_cloak|Woodland Cloak]]?  Good.  Put it on Efraim and send him through the woods.  Take your time, there is no early finish bonus.  While the objectives say killing orcs is optional, it's also a lot of fun.  Force the orcs in the east to come at you through the river, or pound your way into their castle so that you control how much they can recruit.  If you've advanced Lethalia to have chill tempest with explosive slow this is a great time to make use of it (this is why you sent Efraim with the Woodlands Cloak).&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' This is a great opportunity to level up some of those dwarfs you recruited in Mining, standing in the mountains to the east of the first orc castle pounding away at slowed orcs and trolls.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Lots of XP harvesting to be done here and villages do produce income. Any unit reaching the western edge is sufficient for victory. Beelezbub's monument, if present, is at 29,20, nicely central and en route to the orc leader.&lt;br /&gt;
&lt;br /&gt;
==Bitter Swamp==&lt;br /&gt;
'''[WHU]''' Send Efraim and Lethalia to work together to carve through the saurians and kill their leader.  Protect weaker units in the castle from saurians appearing out of the swamp.  After several turns, Efraim and Lethalia should draw the undead coming from the northwest to them, allowing a couple units such as Delly and Stormrider to advance easily up the path and kill the lich.  There is a trader north of your castle.  You might as well spend most of your gold now.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Watch out for nearly invisible Fog with petrify attack. I ended up wanting about 800 gold to spend at the Trader.&lt;br /&gt;
&lt;br /&gt;
==First Confrontation==&lt;br /&gt;
'''[WHU]''' The obvious approach here would probably be to stand on the bank of the river and slaughter a bunch of drakes.  This will work, but will probably be costly.  A simpler approach is to send Efraim and Lethalia forward at full speed, right through the middle of the pack of drakes, while defensive units surround the castle protecting weaker ones.  The drakes will concentrate almost exclusively on Efraim and Lethalia, sending only a handful south that you can easily dispatch.  &lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' There's no early finish bonus.  The drake leader has a lot of gold and a healthy income.  If you want to milk drakes for XP, you will want to consider whether or not to kill him early (less danger if you want to get XP for your army) or not (more drakes to kill).&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' If Beelezebub is present, I recruit a Faerie and two seers for extra firepower. I find I want to carry ~700 gold over into next scenario.&lt;br /&gt;
&lt;br /&gt;
==Chasing Dragons==&lt;br /&gt;
'''[WHU]''' Send someone into the cavern in the mountains and touch the obelisk.  The instructions are more or less written backwards.  Or don't, it's not like you'll need the help.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' Send Efraim and Lethalia separately at two of the nearest dragon leaders.  Send the rest of your powerful units along the path and across the bridge to assist your allies.  Your allies can pretty much take care of things, so don't put any units at risk.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' As dragon after dragon attack Efraim and Lethalia and basically bounce off, try not to laugh.  It's not polite.&lt;br /&gt;
&lt;br /&gt;
'''[WHU]''' The end of this scenario is probably a really good time to strip Argan, Delly, and Stormrider of any gear.&lt;br /&gt;
&lt;br /&gt;
'''[Thrash]''' Note four units to recall in Chapter 4. This is the last time you play Delly and Argan, so unequip them of any items for certain. Other units won't be available in next chapter, so you might want to unequip them as well. Those units here won't be available to you again until Chapter 5, when you can recall them with Soulgate; this picks them randomly, so it's not a bad idea to go through and clear up your recall list, getting rid of weaker units.&lt;br /&gt;
&lt;br /&gt;
==Nightmare==&lt;br /&gt;
'''[WHU]''' After all the fun we had with dragons in the last scenario, might as well go after them again.  &lt;br /&gt;
 &lt;br /&gt;
'''[Thrash]''' I generally recruit a bunch of units to distract the enemy and then flee to a corner or other area with limited access. If needed, use some healing potions. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
| style=&amp;quot;text-align: left;width: 33%&amp;quot; | [[LotI_Walkthrough-Part1-Chapter02|Back to Chapter 2]] &lt;br /&gt;
| style=&amp;quot;text-align: center;width: 33%&amp;quot; | [[LotI_Walkthrough|Main]] &lt;br /&gt;
| style=&amp;quot;text-align: right;width: 33%&amp;quot; | [[LotI_Walkthrough-Part1-Chapter04|On to Chapter 4]] &lt;br /&gt;
|}&lt;br /&gt;
[[LotI_Walkthrough|Back]]&lt;/div&gt;</summary>
		<author><name>White haired uncle</name></author>
		
	</entry>
</feed>