Custom themes can be shared with other TGUI users via the Themes forum section.
To create your own themes, you can use the existing themes (which can be found in the “themes” subfolder of TGUI) as a starting point.
The theme file contains of multiple sections, each having a name and its contents between braces. Within a section, you write property-value pairs with an equal sign in between and a semicolon at the end. Whitespace is ignored.
Button {
Property1 = Value1;
Property2 = Value2;
}
The name of the section can be freely chosen. The name will however usually be the same as the widget type, as this is what a widget will attempt to load from the default theme (e.g. slider widget will search for a section called “Slider”). If you set a renderer to the widget after loading then you can hower choose to load a section with any name. So you can have sections like “BlueButton” and “RedButton”, the created buttons just won’t load them by default.
The property names have to correspond with what the widget supports. If the section is going to be used as renderer for a RadioButton then the properties should match the ones found in the RadioButtonRenderer. The renderer has e.g. setTextColor and getTextColor functions, so the property in the theme file would be called TextColor (case-sensitive).
Different properties have different types. Which type should be obvious when looking at the renderer. The “TextColor” property for example should be given a color as value. An explanation on how a value of each type should look like can be found below.
Comments can also be added to the file by using either //
for single line comments or wrapping the contents in /*
and */
.
Although simple strings don’t need quotes around them, it is recommended to always write quotes around your string value. Escaping works the same way as in c++, by using a backslash in front of the character:
Text = "String with \\, \" and even a \n inside it";
Numbers don’t require much explanation:
Opacity = 0.7;
DistanceToSide = 5;
There are 3 ways to encode a color:
The predefined colors should be treated as case-sensitive (even though TGUI currently allows case-insensitive color values). The possible values correspond to the color constants in c++.
TextColor = #00FF007F;
BackgroundColor = rgb(0, 255, 255);
BorderColor = Green;
Values of textures can contain multiple optional properties, but the only mandatory part of the value is a filename between quotes. Unless an absolute path is provided, the path will be considered relative to the location of the theme file.
Texture = "image.png";
A “Part” rectangle can be provided to load only a part of the image. If not present then the entire image would be loaded. The following line would load an area of 50x30 pixels starting from position (20,10) in the image:
Texture = "image.png" Part(20, 10, 50, 30);
A “Middle” rectangle can be provided to specify how the image should be scaled. If a Part rectangle is given then the Middle rectangle is relative to it (i.e. the part is first extracted from the image and the Middle rectangle acts as if this part of the image is the entire image). Just like the Part rectangle, the Middle is provided in the (left, top, width, height) format.
Texture = "image.png" Part(20, 10, 50, 30) Middle(6, 6, 38, 18);
There are 4 ways that an image can be scaled:
Because in almost all cases you want the space on the left and top in the middle rectangle to be equal to the space on the right and bottom, you can also specify it with only 2 values. Specifying (x,y)
is equivalent to (x, y, width - 2*x, height - 2*y)
.
Texture = "image.png" Part(20, 10, 50, 30) Middle(6, 6);
At the very end of the value, the “Smooth” or “NoSmooth” word can be added to override the default setting (which can be set with the static tgui::Texture::setDefaultSmooth(bool)
function). The NoSmooth option will use Nearest Neighbor while the Smooth option will choose bilinear interpolation when scaling the image.
Texture = "image.png" NoSmooth;
Texture = "image.png" Middle(10, 10) Smooth;
Borders and Padding properties use an Outline type. Four values have to be provided, representing the border/padding thickness on the left, top, right and bottom sides. When only 2 values are provided then they are parsed as left/right and top/bottom thickness. If only one value is provided then the outline will have the same size on all sides.
Borders = (1, 2, 3, 4);
Borders = (1, 2); // Same as (1, 2, 1, 2)
Borders = (1); // Same as (1, 1, 1, 1)
Some widgets might contain other widgets (e.g. ChildWindow contains a close button and multiple widgets contain a scrollbar). In these cases their renderer also contains the renderer for the subwidget.
TextArea {
BackgroundColor = Red; // Background color of ListBox
ScrollBar = {
BackgroundColor = Green; // Background color of vertical and horizontal scrollbar inside TextArea
};
}
You probably want all scrollbars to look the same way. Instead of repeating the renderer properties for the scrollbar in each scrollable widget, you can also have a single scrollbar section and refer to it inside the scrollable widgets. When refering to another section, the value should consist of an ampersand followed by the section name.
CustomScrollbarSection {
}
TextArea {
Scrollbar = &CustomScrollbarSection;
}
In most cases you don’t actually need to manually specify the scrollbar each time though. If a Scrollbar section exists, widgets with scrollbars will have their Scrollbar property automatically reference to it. Below is a list of all properties that act like this. If the first column in this table is ChildWindow.CloseButton
and the second column Button
, it means that if you don’t specify a CloseButton
property inside the ChildWindow
section then it’s value will default to what is specified by the Button
section in the theme file.
Property | Referenced section |
---|---|
ChatBox.Scrollbar | Scrollbar |
ChildWindow.CloseButton | Button |
ColorPicker.Button | Button |
ColorPicker.Label | Label |
ColorPicker.Slider | Slider |
ComboBox.ListBox | ListBox |
FileDialog.Button | Button |
FileDialog.EditBox | EditBox |
FileDialog.ListView | ListView |
FileDialog.FilenameLabel | Label |
FileDialog.FileTypeComboBox | ComboBox |
Label.Scrollbar | Scrollbar |
ListBox.Scrollbar | Scrollbar |
ListView.Scrollbar | Scrollbar |
MessageBox.Button | Button |
ScrollablePanel.Scrollbar | Scrollbar |
SpinControl.SpinButton | SpinButton |
SpinControl.SpinText | EditBox |
TextArea.Scrollbar | Scrollbar |
TreeView.Scrollbar | Scrollbar |
If a section needs the same properties as another one, you can let one inherit from the other to copy its values. In the example below will, BlueButton will copy all values of the Button section, except for the background color which is given a different value.
BlueButton : Button {
BackgroundColor = Blue;
}
TGUI contains a few built-in inheritance rules for sections that aren’t specified. For example, ListView will inherit all properties from ListBox if you don’t explicitly specify a ListView section in your theme. This means your theme only needs a ListBox section and the ListView widget will automatically look similar. If you do specify a ListView section in your theme though (to e.g. specify HeaderTextColor
which ListBox doesn’t have), then you should perform the inheritance manually by creating the section with ListView : ListBox { ... }
.
Here is a list of all sections that are automatically created if they don’t appear in the theme file:
Unspecified section | Inherits from |
---|---|
BitmapButton | Button |
CheckBox | RadioButton |
ColorPicker | ChildWindow |
FileDialog | ChildWindow |
ListView | ListBox |
MessageBox | ChildWindow |
RangeSlider | Slider |
RichTextLabel | Label |
ScrollablePanel | Panel |
PanelListBox | ScrollablePanel |
ToggleButton | Button |
TreeView | ListBox |
It is possible to have global properties in the theme file, i.e. properties that aren’t inside any section. TGUI contains a hardcoded inheritance list where properties that aren’t specified can fall back to global properties. In practice this means that if you specify “TextColor = Black;
” at the top of the theme file, all widgets will have a black text color (unless the TextColor property is redefined in the widget’s section).
The following properties can be specified in the global scope of the theme file:
TextColor |
TextColorHover |
TextColorDisabled |
BackgroundColor |
BackgroundColorHover |
BackgroundColorDisabled |
SelectedTextColor |
SelectedTextColorHover |
SelectedBackgroundColor |
SelectedBackgroundColorHover |
BorderColor |
Borders |
ScrollbarWidth |
ArrowBackgroundColor |
ArrowBackgroundColorHover |
ArrowBackgroundColorDisabled |
ArrowColor |
ArrowColorHover |
ArrowColorDisabled |
Some widgets have default values inherited from global properties that have a different name. The following table lists these special cases. If in this list the property name is WidgetName.PropertyName
, it is referring to a property called PropertyName
that is placed inside a section called WidgetName
.
Property | Inherited global property |
---|---|
BorderColor | TextColor |
ArrowColor | TextColor |
ArrowBackgroundColor | BackgroundColor |
ChildWindow.TitleColor | TextColor |
EditBox.SelectedTextBackgroundColor | SelectedBackgroundColor |
Knob.ThumbColor | TextColor |
MenuBar.SeparatorColor | BorderColor |
ProgressBar.FillColor | SelectedBackgroundColor |
RadioButton.CheckColor | TextColor |
RangeSlider.SelectedTrackColor | SelectedBackgroundColor |
RangeSlider.SelectedTrackColorHover | SelectedBackgroundColorHover |
Scrollbar.TrackColor | BackgroundColor |
Scrollbar.ThumbColor | ArrowColor |
SeparatorLine.Color | BorderColor |
Slider.TrackColor | BackgroundColor |
Slider.ThumbColor | ArrowColor |
TextArea.SelectedTextBackgroundColor | SelectedBackgroundColor |
TextArea.CaretColor | TextColor |
ToggleButton.TextColorDown | SelectedTextColor |
ToggleButton.BackgroundColorDown | SelectedBackgroundColor |