mirror of
https://github.com/minetest/minetest.git
synced 2024-12-24 07:02:23 +01:00
Add styles to most elements
This commit is contained in:
parent
ec3795a55c
commit
9541165752
@ -177,6 +177,7 @@ LOCAL_SRC_FILES := \
|
|||||||
jni/src/filesys.cpp \
|
jni/src/filesys.cpp \
|
||||||
jni/src/genericobject.cpp \
|
jni/src/genericobject.cpp \
|
||||||
jni/src/gettext.cpp \
|
jni/src/gettext.cpp \
|
||||||
|
jni/src/gui/guiButton.cpp \
|
||||||
jni/src/gui/guiChatConsole.cpp \
|
jni/src/gui/guiChatConsole.cpp \
|
||||||
jni/src/gui/guiConfirmRegistration.cpp \
|
jni/src/gui/guiConfirmRegistration.cpp \
|
||||||
jni/src/gui/guiEditBoxWithScrollbar.cpp \
|
jni/src/gui/guiEditBoxWithScrollbar.cpp \
|
||||||
|
@ -22,7 +22,7 @@ local function delete_content_formspec(dialogdata)
|
|||||||
"size[11.5,4.5,true]" ..
|
"size[11.5,4.5,true]" ..
|
||||||
"label[2,2;" ..
|
"label[2,2;" ..
|
||||||
fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name) .. "]"..
|
fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name) .. "]"..
|
||||||
"style[dlg_delete_content_confirm;bgcolor;red]" ..
|
"style[dlg_delete_content_confirm;bgcolor=red]" ..
|
||||||
"button[3.25,3.5;2.5,0.5;dlg_delete_content_confirm;" .. fgettext("Delete") .. "]" ..
|
"button[3.25,3.5;2.5,0.5;dlg_delete_content_confirm;" .. fgettext("Delete") .. "]" ..
|
||||||
"button[5.75,3.5;2.5,0.5;dlg_delete_content_cancel;" .. fgettext("Cancel") .. "]"
|
"button[5.75,3.5;2.5,0.5;dlg_delete_content_cancel;" .. fgettext("Cancel") .. "]"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ local function delete_world_formspec(dialogdata)
|
|||||||
"size[10,2.5,true]" ..
|
"size[10,2.5,true]" ..
|
||||||
"label[0.5,0.5;" ..
|
"label[0.5,0.5;" ..
|
||||||
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
|
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
|
||||||
"style[world_delete_confirm;bgcolor;red]" ..
|
"style[world_delete_confirm;bgcolor=red]" ..
|
||||||
"button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
|
"button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
|
||||||
"button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
|
"button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
|
||||||
return retval
|
return retval
|
||||||
|
@ -102,9 +102,6 @@ local function get_formspec(tabview, name, tabdata)
|
|||||||
)
|
)
|
||||||
|
|
||||||
retval = retval ..
|
retval = retval ..
|
||||||
"style_type[button;bgcolor;#006699]" ..
|
|
||||||
"style[world_delete;bgcolor;red]" ..
|
|
||||||
"style[world_delete;textcolor;yellow]" ..
|
|
||||||
"button[4,3.95;2.6,1;world_delete;".. fgettext("Delete") .. "]" ..
|
"button[4,3.95;2.6,1;world_delete;".. fgettext("Delete") .. "]" ..
|
||||||
"button[6.5,3.95;2.8,1;world_configure;".. fgettext("Configure") .. "]" ..
|
"button[6.5,3.95;2.8,1;world_configure;".. fgettext("Configure") .. "]" ..
|
||||||
"button[9.2,3.95;2.5,1;world_create;".. fgettext("New") .. "]" ..
|
"button[9.2,3.95;2.5,1;world_create;".. fgettext("New") .. "]" ..
|
||||||
|
103
doc/lua_api.txt
103
doc/lua_api.txt
@ -1884,7 +1884,10 @@ When displaying text which can contain formspec code, e.g. text set by a player,
|
|||||||
use `minetest.formspec_escape`.
|
use `minetest.formspec_escape`.
|
||||||
For coloured text you can use `minetest.colorize`.
|
For coloured text you can use `minetest.colorize`.
|
||||||
|
|
||||||
WARNING: Minetest allows you to add elements to every single formspec instance
|
**WARNING**: do _not_ use a element name starting with `key_`; those names are
|
||||||
|
reserved to pass key press events to formspec!
|
||||||
|
|
||||||
|
**WARNING**: Minetest allows you to add elements to every single formspec instance
|
||||||
using `player:set_formspec_prepend()`, which may be the reason backgrounds are
|
using `player:set_formspec_prepend()`, which may be the reason backgrounds are
|
||||||
appearing when you don't expect them to, or why things are styled differently
|
appearing when you don't expect them to, or why things are styled differently
|
||||||
to normal. See [`no_prepend[]`] and [Styling Formspecs].
|
to normal. See [`no_prepend[]`] and [Styling Formspecs].
|
||||||
@ -2351,22 +2354,17 @@ Elements
|
|||||||
* `span=<value>`: number of following columns to affect
|
* `span=<value>`: number of following columns to affect
|
||||||
(default: infinite).
|
(default: infinite).
|
||||||
|
|
||||||
**Note**: do _not_ use a element name starting with `key_`; those names are
|
### `style[<name>;<prop1>;<prop2>;...]`
|
||||||
reserved to pass key press events to formspec!
|
|
||||||
|
|
||||||
### `style[<name>;<propery>;<value]`
|
* Set the style for the named element `name`.
|
||||||
|
* Note: this **must** be before the element is defined.
|
||||||
Set the style for the named element `name`.
|
* See [Styling Formspecs].
|
||||||
Note: this **must** be before the element's tag.
|
|
||||||
|
|
||||||
See [Styling Formspecs].
|
|
||||||
|
|
||||||
|
|
||||||
### `style_type[<type>;<propery>;<value>]`
|
### `style_type[<type>;<prop1>;<prop2>;...]`
|
||||||
|
|
||||||
Sets the style for all elements of type `type` which appear after this tag.
|
* Sets the style for all elements of type `type` which appear after this element.
|
||||||
|
* See [Styling Formspecs].
|
||||||
See [Styling Formspecs].
|
|
||||||
|
|
||||||
Migrating to Real Coordinates
|
Migrating to Real Coordinates
|
||||||
-----------------------------
|
-----------------------------
|
||||||
@ -2406,27 +2404,82 @@ offsets when migrating:
|
|||||||
Styling Formspecs
|
Styling Formspecs
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Formspec elements can be themed using the style tags:
|
Formspec elements can be themed using the style elements:
|
||||||
|
|
||||||
style[ELEMENT_NAME;PROPERTY;VALUE]
|
style[<name>;<prop1>;<prop2>;...]
|
||||||
style_type[ELEMENT_TYPE;PROPERTY;VALUE]
|
style_type[<type>;<prop1>;<prop2>;...]
|
||||||
|
|
||||||
|
Where a prop is:
|
||||||
|
|
||||||
|
property_name=property_value
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
style_type[button;bgcolor;#006699]
|
style_type[button;bgcolor=#006699]
|
||||||
style[world_delete;bgcolor;#ff0000]
|
style[world_delete;bgcolor=red;textcolor=yellow]
|
||||||
button[4,3.95;2.6,1;world_delete;Delete]
|
button[4,3.95;2.6,1;world_delete;Delete]
|
||||||
|
|
||||||
|
Setting a property to nothing will reset it to the default value. For example:
|
||||||
|
|
||||||
|
style_type[button;bgimg=button.png;bgimg_pressed=button_pressed.png;border=false]
|
||||||
|
style[btn_exit;bgimg=;bgimg_pressed=;border=;bgcolor=red]
|
||||||
|
|
||||||
|
|
||||||
|
### Supported Element Types
|
||||||
|
|
||||||
|
Some types may inherit styles from parent types.
|
||||||
|
|
||||||
|
* button
|
||||||
|
* button_exit, inherits from button
|
||||||
|
* checkbox
|
||||||
|
* scrollbar
|
||||||
|
* table
|
||||||
|
* textlist
|
||||||
|
* dropdown
|
||||||
|
* field
|
||||||
|
* pwdfield, inherits from field
|
||||||
|
* textarea
|
||||||
|
* label
|
||||||
|
* vertlabel, inherits from field
|
||||||
|
* image_button
|
||||||
|
* item_image_button, inherits from image_button
|
||||||
|
* tabheader
|
||||||
|
|
||||||
|
|
||||||
### Valid Properties
|
### Valid Properties
|
||||||
|
|
||||||
* button and button_exit
|
* button, button_exit
|
||||||
* bgcolor - sets button tint
|
* bgcolor - color, sets button tint
|
||||||
* textcolor
|
* textcolor - color, default white
|
||||||
|
* border - boolean, draw border. Set to false to hide the bevelled button pane. Default true.
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* bgimg - standard image. Defaults to none.
|
||||||
|
* bgimg_pressed - image when pressed. Defaults to bgimg when not provided.
|
||||||
|
* alpha - boolean, whether to draw alpha in bgimg. Default true.
|
||||||
|
* checkbox
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* scrollbar
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* table, textlist
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* dropdown
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* field, pwdfield, textarea
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* border - set to false to hide the textbox background and border. Default true.
|
||||||
|
* textcolor - color. Default white.
|
||||||
|
* label, vertlabel
|
||||||
|
* bgcolor - color. Default unset.
|
||||||
|
* textcolor - color. Default white.
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* border - boolean, set to true to get a border. Default true.
|
||||||
|
* image_button, item_image_button
|
||||||
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
|
* border - boolean, draw border. Set to false to hide the bevelled button pane. Default false.
|
||||||
|
* alpha - boolean, whether to draw alpha in bgimg. Default true.
|
||||||
* tabheader
|
* tabheader
|
||||||
* bgcolor - tab background
|
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
|
||||||
* textcolor
|
* textcolor - color. Default white.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Inventory
|
Inventory
|
||||||
=========
|
=========
|
||||||
|
@ -61,7 +61,7 @@ static gui::GUISkin* createSkin(gui::IGUIEnvironment *environment,
|
|||||||
gui::GUISkin *skin = new gui::GUISkin(type, driver);
|
gui::GUISkin *skin = new gui::GUISkin(type, driver);
|
||||||
|
|
||||||
gui::IGUIFont *builtinfont = environment->getBuiltInFont();
|
gui::IGUIFont *builtinfont = environment->getBuiltInFont();
|
||||||
gui::IGUIFontBitmap* bitfont = 0;
|
gui::IGUIFontBitmap *bitfont = nullptr;
|
||||||
if (builtinfont && builtinfont->getType() == gui::EGFT_BITMAP)
|
if (builtinfont && builtinfont->getType() == gui::EGFT_BITMAP)
|
||||||
bitfont = (gui::IGUIFontBitmap*)builtinfont;
|
bitfont = (gui::IGUIFontBitmap*)builtinfont;
|
||||||
|
|
||||||
|
@ -18,85 +18,118 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
class StyleSpec
|
class StyleSpec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Property {
|
enum Property
|
||||||
NONE = 0,
|
{
|
||||||
TEXTCOLOR,
|
TEXTCOLOR,
|
||||||
BGCOLOR,
|
BGCOLOR,
|
||||||
NUM_PROPERTIES
|
NOCLIP,
|
||||||
|
BORDER,
|
||||||
|
BGIMG,
|
||||||
|
BGIMG_PRESSED,
|
||||||
|
ALPHA,
|
||||||
|
NUM_PROPERTIES,
|
||||||
|
NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<Property, std::string> properties;
|
std::array<bool, NUM_PROPERTIES> property_set;
|
||||||
|
std::array<std::string, NUM_PROPERTIES> properties;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Property GetPropertyByName(const std::string &name) {
|
static Property GetPropertyByName(const std::string &name)
|
||||||
|
{
|
||||||
if (name == "textcolor") {
|
if (name == "textcolor") {
|
||||||
return TEXTCOLOR;
|
return TEXTCOLOR;
|
||||||
} else if (name == "bgcolor") {
|
} else if (name == "bgcolor") {
|
||||||
return BGCOLOR;
|
return BGCOLOR;
|
||||||
|
} else if (name == "noclip") {
|
||||||
|
return NOCLIP;
|
||||||
|
} else if (name == "border") {
|
||||||
|
return BORDER;
|
||||||
|
} else if (name == "bgimg") {
|
||||||
|
return BGIMG;
|
||||||
|
} else if (name == "bgimg_pressed") {
|
||||||
|
return BGIMG_PRESSED;
|
||||||
|
} else if (name == "alpha") {
|
||||||
|
return ALPHA;
|
||||||
} else {
|
} else {
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get(Property prop, std::string def) const {
|
std::string get(Property prop, std::string def) const
|
||||||
auto it = properties.find(prop);
|
{
|
||||||
if (it == properties.end()) {
|
const auto &val = properties[prop];
|
||||||
|
return val.empty() ? def : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(Property prop, const std::string &value)
|
||||||
|
{
|
||||||
|
properties[prop] = value;
|
||||||
|
property_set[prop] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::SColor getColor(Property prop, video::SColor def) const
|
||||||
|
{
|
||||||
|
const auto &val = properties[prop];
|
||||||
|
if (val.empty()) {
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
return it->second;
|
parseColorString(val, def, false, 0xFF);
|
||||||
}
|
|
||||||
|
|
||||||
void set(Property prop, std::string value) {
|
|
||||||
properties[prop] = std::move(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
video::SColor getColor(Property prop, video::SColor def) const {
|
|
||||||
auto it = properties.find(prop);
|
|
||||||
if (it == properties.end()) {
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseColorString(it->second, def, false, 0xFF);
|
video::SColor getColor(Property prop) const
|
||||||
return def;
|
{
|
||||||
}
|
const auto &val = properties[prop];
|
||||||
|
FATAL_ERROR_IF(val.empty(), "Unexpected missing property");
|
||||||
video::SColor getColor(Property prop) const {
|
|
||||||
auto it = properties.find(prop);
|
|
||||||
FATAL_ERROR_IF(it == properties.end(), "Unexpected missing property");
|
|
||||||
|
|
||||||
video::SColor color;
|
video::SColor color;
|
||||||
parseColorString(it->second, color, false, 0xFF);
|
parseColorString(val, color, false, 0xFF);
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasProperty(Property prop) const {
|
bool getBool(Property prop, bool def) const
|
||||||
return properties.find(prop) != properties.end();
|
{
|
||||||
|
const auto &val = properties[prop];
|
||||||
|
if (val.empty()) {
|
||||||
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleSpec &operator|=(const StyleSpec &other) {
|
return is_yes(val);
|
||||||
for (size_t i = 1; i < NUM_PROPERTIES; i++) {
|
}
|
||||||
|
|
||||||
|
inline bool isNotDefault(Property prop) const
|
||||||
|
{
|
||||||
|
return !properties[prop].empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool hasProperty(Property prop) const { return property_set[prop]; }
|
||||||
|
|
||||||
|
StyleSpec &operator|=(const StyleSpec &other)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < NUM_PROPERTIES; i++) {
|
||||||
auto prop = (Property)i;
|
auto prop = (Property)i;
|
||||||
if (other.hasProperty(prop)) {
|
if (other.hasProperty(prop)) {
|
||||||
properties[prop] = other.get(prop, "");
|
set(prop, other.get(prop, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleSpec operator|(const StyleSpec &other) const {
|
StyleSpec operator|(const StyleSpec &other) const
|
||||||
|
{
|
||||||
StyleSpec newspec = *this;
|
StyleSpec newspec = *this;
|
||||||
newspec |= other;
|
newspec |= other;
|
||||||
return newspec;
|
return newspec;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -500,6 +500,9 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element
|
|||||||
gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this,
|
gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this,
|
||||||
spec.fid, spec.flabel.c_str());
|
spec.fid, spec.flabel.c_str());
|
||||||
|
|
||||||
|
auto style = getStyleForElement("checkbox", name);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
|
||||||
if (spec.fname == data->focused_fieldname) {
|
if (spec.fname == data->focused_fieldname) {
|
||||||
Environment->setFocus(e);
|
Environment->setFocus(e);
|
||||||
}
|
}
|
||||||
@ -556,6 +559,9 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
|
|||||||
gui::IGUIScrollBar* e =
|
gui::IGUIScrollBar* e =
|
||||||
Environment->addScrollBar(is_horizontal,rect,this,spec.fid);
|
Environment->addScrollBar(is_horizontal,rect,this,spec.fid);
|
||||||
|
|
||||||
|
auto style = getStyleForElement("scrollbar", name);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
|
||||||
e->setMax(1000);
|
e->setMax(1000);
|
||||||
e->setMin(0);
|
e->setMin(0);
|
||||||
e->setPos(stoi(parts[4]));
|
e->setPos(stoi(parts[4]));
|
||||||
@ -702,15 +708,35 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
|
|||||||
|
|
||||||
GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str());
|
GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str());
|
||||||
|
|
||||||
auto style = getThemeForElement(type, name);
|
auto style = getStyleForElement(type, name, (type != "button") ? "button" : "");
|
||||||
if (style.hasProperty(StyleSpec::BGCOLOR)) {
|
if (style.isNotDefault(StyleSpec::BGCOLOR)) {
|
||||||
e->setColor(style.getColor(StyleSpec::BGCOLOR));
|
e->setColor(style.getColor(StyleSpec::BGCOLOR));
|
||||||
}
|
}
|
||||||
if (style.hasProperty(StyleSpec::TEXTCOLOR)) {
|
if (style.isNotDefault(StyleSpec::TEXTCOLOR)) {
|
||||||
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR));
|
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR));
|
||||||
}
|
}
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, true));
|
||||||
|
|
||||||
// e->setSprite();
|
if (style.isNotDefault(StyleSpec::BGIMG)) {
|
||||||
|
std::string image_name = style.get(StyleSpec::BGIMG, "");
|
||||||
|
std::string pressed_image_name = style.get(StyleSpec::BGIMG_PRESSED, "");
|
||||||
|
|
||||||
|
video::ITexture *texture = 0;
|
||||||
|
video::ITexture *pressed_texture = 0;
|
||||||
|
texture = m_tsrc->getTexture(image_name);
|
||||||
|
if (!pressed_image_name.empty())
|
||||||
|
pressed_texture = m_tsrc->getTexture(pressed_image_name);
|
||||||
|
else
|
||||||
|
pressed_texture = texture;
|
||||||
|
|
||||||
|
e->setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true));
|
||||||
|
e->setImage(guiScalingImageButton(
|
||||||
|
Environment->getVideoDriver(), texture, geom.X, geom.Y));
|
||||||
|
e->setPressedImage(guiScalingImageButton(
|
||||||
|
Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));
|
||||||
|
e->setScaleImage(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (spec.fname == data->focused_fieldname) {
|
if (spec.fname == data->focused_fieldname) {
|
||||||
Environment->setFocus(e);
|
Environment->setFocus(e);
|
||||||
@ -889,6 +915,9 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
|
|||||||
if (!str_initial_selection.empty() && str_initial_selection != "0")
|
if (!str_initial_selection.empty() && str_initial_selection != "0")
|
||||||
e->setSelected(stoi(str_initial_selection));
|
e->setSelected(stoi(str_initial_selection));
|
||||||
|
|
||||||
|
auto style = getStyleForElement("table", name);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
|
||||||
m_tables.emplace_back(spec, e);
|
m_tables.emplace_back(spec, e);
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
return;
|
return;
|
||||||
@ -963,6 +992,9 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
|
|||||||
if (!str_initial_selection.empty() && str_initial_selection != "0")
|
if (!str_initial_selection.empty() && str_initial_selection != "0")
|
||||||
e->setSelected(stoi(str_initial_selection));
|
e->setSelected(stoi(str_initial_selection));
|
||||||
|
|
||||||
|
auto style = getStyleForElement("textlist", name);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
|
||||||
m_tables.emplace_back(spec, e);
|
m_tables.emplace_back(spec, e);
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
return;
|
return;
|
||||||
@ -1035,6 +1067,9 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element
|
|||||||
if (!str_initial_selection.empty())
|
if (!str_initial_selection.empty())
|
||||||
e->setSelected(stoi(str_initial_selection)-1);
|
e->setSelected(stoi(str_initial_selection)-1);
|
||||||
|
|
||||||
|
auto style = getStyleForElement("dropdown", name);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
|
|
||||||
m_dropdowns.emplace_back(spec, std::vector<std::string>());
|
m_dropdowns.emplace_back(spec, std::vector<std::string>());
|
||||||
@ -1118,6 +1153,11 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element
|
|||||||
|
|
||||||
e->setPasswordBox(true,L'*');
|
e->setPasswordBox(true,L'*');
|
||||||
|
|
||||||
|
auto style = getStyleForElement("pwdfield", name, "field");
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, true));
|
||||||
|
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
|
||||||
|
|
||||||
irr::SEvent evt;
|
irr::SEvent evt;
|
||||||
evt.EventType = EET_KEY_INPUT_EVENT;
|
evt.EventType = EET_KEY_INPUT_EVENT;
|
||||||
evt.KeyInput.Key = KEY_END;
|
evt.KeyInput.Key = KEY_END;
|
||||||
@ -1194,6 +1234,14 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec,
|
|||||||
evt.KeyInput.PressedDown = true;
|
evt.KeyInput.PressedDown = true;
|
||||||
e->OnEvent(evt);
|
e->OnEvent(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto style = getStyleForElement(is_multiline ? "textarea" : "field", spec.fname);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, true));
|
||||||
|
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
|
||||||
|
if (style.get(StyleSpec::BGCOLOR, "") == "transparent") {
|
||||||
|
e->setDrawBackground(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spec.flabel.empty()) {
|
if (!spec.flabel.empty()) {
|
||||||
@ -1407,6 +1455,15 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
|
|||||||
gui::IGUIStaticText *e = gui::StaticText::add(Environment,
|
gui::IGUIStaticText *e = gui::StaticText::add(Environment,
|
||||||
spec.flabel.c_str(), rect, false, false, this, spec.fid);
|
spec.flabel.c_str(), rect, false, false, this, spec.fid);
|
||||||
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER);
|
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER);
|
||||||
|
|
||||||
|
auto style = getStyleForElement("label", spec.fname);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, false));
|
||||||
|
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
|
||||||
|
if (style.isNotDefault(StyleSpec::BGCOLOR)) {
|
||||||
|
e->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR));
|
||||||
|
}
|
||||||
|
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1475,9 +1532,18 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen
|
|||||||
L"",
|
L"",
|
||||||
258+m_fields.size()
|
258+m_fields.size()
|
||||||
);
|
);
|
||||||
gui::IGUIStaticText *t = gui::StaticText::add(Environment, spec.flabel.c_str(),
|
gui::IGUIStaticText *e = gui::StaticText::add(Environment, spec.flabel.c_str(),
|
||||||
rect, false, false, this, spec.fid);
|
rect, false, false, this, spec.fid);
|
||||||
t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
|
||||||
|
|
||||||
|
auto style = getStyleForElement("vertlabel", spec.fname, "label");
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, false));
|
||||||
|
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
|
||||||
|
if (style.isNotDefault(StyleSpec::BGCOLOR)) {
|
||||||
|
e->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR));
|
||||||
|
}
|
||||||
|
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1563,14 +1629,21 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem
|
|||||||
Environment->setFocus(e);
|
Environment->setFocus(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
e->setUseAlphaChannel(true);
|
auto style = getStyleForElement("image_button", spec.fname);
|
||||||
|
|
||||||
|
e->setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true));
|
||||||
e->setImage(guiScalingImageButton(
|
e->setImage(guiScalingImageButton(
|
||||||
Environment->getVideoDriver(), texture, geom.X, geom.Y));
|
Environment->getVideoDriver(), texture, geom.X, geom.Y));
|
||||||
e->setPressedImage(guiScalingImageButton(
|
e->setPressedImage(guiScalingImageButton(
|
||||||
Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));
|
Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));
|
||||||
e->setScaleImage(true);
|
e->setScaleImage(true);
|
||||||
|
if (parts.size() >= 7) {
|
||||||
e->setNotClipped(noclip);
|
e->setNotClipped(noclip);
|
||||||
e->setDrawBorder(drawborder);
|
e->setDrawBorder(drawborder);
|
||||||
|
} else {
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, true));
|
||||||
|
}
|
||||||
|
|
||||||
m_fields.push_back(spec);
|
m_fields.push_back(spec);
|
||||||
return;
|
return;
|
||||||
@ -1656,7 +1729,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen
|
|||||||
pos.Y+geom.Y);
|
pos.Y+geom.Y);
|
||||||
|
|
||||||
gui::IGUITabControl *e = Environment->addTabControl(rect, this,
|
gui::IGUITabControl *e = Environment->addTabControl(rect, this,
|
||||||
false, show_border, spec.fid);
|
show_background, show_border, spec.fid);
|
||||||
e->setAlignment(irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT,
|
e->setAlignment(irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT,
|
||||||
irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_LOWERRIGHT);
|
irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_LOWERRIGHT);
|
||||||
e->setTabHeight(geom.Y);
|
e->setTabHeight(geom.Y);
|
||||||
@ -1665,16 +1738,13 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen
|
|||||||
Environment->setFocus(e);
|
Environment->setFocus(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
e->setNotClipped(true);
|
auto style = getStyleForElement("tabheader", name);
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, true));
|
||||||
auto style = getThemeForElement("tabheader", name);
|
|
||||||
|
|
||||||
for (const std::string &button : buttons) {
|
for (const std::string &button : buttons) {
|
||||||
auto tab = e->addTab(unescape_translate(unescape_string(
|
auto tab = e->addTab(unescape_translate(unescape_string(
|
||||||
utf8_to_wide(button))).c_str(), -1);
|
utf8_to_wide(button))).c_str(), -1);
|
||||||
tab->setDrawBackground(false);
|
if (style.isNotDefault(StyleSpec::BGCOLOR))
|
||||||
tab->setBackgroundColor(video::SColor(0xFFFF0000));
|
|
||||||
if (style.hasProperty(StyleSpec::BGCOLOR))
|
|
||||||
tab->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR));
|
tab->setBackgroundColor(style.getColor(StyleSpec::BGCOLOR));
|
||||||
|
|
||||||
tab->setTextColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
|
tab->setTextColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
|
||||||
@ -1753,6 +1823,10 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
|
|||||||
|
|
||||||
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, L"");
|
gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, L"");
|
||||||
|
|
||||||
|
auto style = getStyleForElement("item_image_button", spec.fname, "image_button");
|
||||||
|
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
|
||||||
|
e->setDrawBorder(style.getBool(StyleSpec::BORDER, true));
|
||||||
|
|
||||||
if (spec.fname == data->focused_fieldname) {
|
if (spec.fname == data->focused_fieldname) {
|
||||||
Environment->setFocus(e);
|
Environment->setFocus(e);
|
||||||
}
|
}
|
||||||
@ -2043,32 +2117,48 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b
|
|||||||
{
|
{
|
||||||
std::vector<std::string> parts = split(element, ';');
|
std::vector<std::string> parts = split(element, ';');
|
||||||
|
|
||||||
if (parts.size() != 3) {
|
if (parts.size() < 2) {
|
||||||
errorstream << "Invalid style element (" << parts.size() << "): '" << element
|
errorstream << "Invalid style element (" << parts.size() << "): '" << element
|
||||||
<< "'" << std::endl;
|
<< "'" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string selector = trim(parts[0]);
|
std::string selector = trim(parts[0]);
|
||||||
std::string propname = trim(parts[1]);
|
if (selector.empty()) {
|
||||||
std::string value = trim(parts[2]);
|
errorstream << "Invalid style element (Selector required): '" << element
|
||||||
|
|
||||||
StyleSpec::Property prop = StyleSpec::GetPropertyByName(propname);
|
|
||||||
if (prop == StyleSpec::NONE) {
|
|
||||||
errorstream << "Invalid style element (Unknown property " << prop << "): '" << element
|
|
||||||
<< "'" << std::endl;
|
<< "'" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleSpec spec;
|
StyleSpec spec;
|
||||||
spec.set(prop, value);
|
|
||||||
|
|
||||||
if (selector.empty()) {
|
for (size_t i = 1; i < parts.size(); i++) {
|
||||||
errorstream << "Invalid style element (Selector required): '" << element
|
size_t equal_pos = parts[i].find('=');
|
||||||
|
if (equal_pos == std::string::npos) {
|
||||||
|
errorstream << "Invalid style element (Property missing value): '" << element
|
||||||
<< "'" << std::endl;
|
<< "'" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string propname = trim(parts[i].substr(0, equal_pos));
|
||||||
|
std::string value = trim(unescape_string(parts[i].substr(equal_pos + 1)));
|
||||||
|
|
||||||
|
std::transform(propname.begin(), propname.end(), propname.begin(), ::tolower);
|
||||||
|
|
||||||
|
StyleSpec::Property prop = StyleSpec::GetPropertyByName(propname);
|
||||||
|
if (prop == StyleSpec::NONE) {
|
||||||
|
if (property_warned.find(propname) != property_warned.end()) {
|
||||||
|
warningstream << "Invalid style element (Unknown property " << propname << "): '"
|
||||||
|
<< element
|
||||||
|
<< "'" << std::endl;
|
||||||
|
property_warned.insert(propname);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.set(prop, value);
|
||||||
|
}
|
||||||
|
|
||||||
if (style_type) {
|
if (style_type) {
|
||||||
theme_by_type[selector] |= spec;
|
theme_by_type[selector] |= spec;
|
||||||
} else {
|
} else {
|
||||||
@ -4115,9 +4205,17 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id)
|
|||||||
return L"";
|
return L"";
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleSpec GUIFormSpecMenu::getThemeForElement(const std::string &type, const std::string &name) {
|
StyleSpec GUIFormSpecMenu::getStyleForElement(const std::string &type,
|
||||||
|
const std::string &name, const std::string &parent_type) {
|
||||||
StyleSpec ret;
|
StyleSpec ret;
|
||||||
|
|
||||||
|
if (!parent_type.empty()) {
|
||||||
|
auto it = theme_by_type.find(parent_type);
|
||||||
|
if (it != theme_by_type.end()) {
|
||||||
|
ret |= it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto it = theme_by_type.find(type);
|
auto it = theme_by_type.find(type);
|
||||||
if (it != theme_by_type.end()) {
|
if (it != theme_by_type.end()) {
|
||||||
ret |= it->second;
|
ret |= it->second;
|
||||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
#include "inventorymanager.h"
|
#include "inventorymanager.h"
|
||||||
@ -404,8 +405,10 @@ protected:
|
|||||||
|
|
||||||
std::unordered_map<std::string, StyleSpec> theme_by_type;
|
std::unordered_map<std::string, StyleSpec> theme_by_type;
|
||||||
std::unordered_map<std::string, StyleSpec> theme_by_name;
|
std::unordered_map<std::string, StyleSpec> theme_by_name;
|
||||||
|
std::unordered_set<std::string> property_warned;
|
||||||
|
|
||||||
StyleSpec getThemeForElement(const std::string &type, const std::string &name);
|
StyleSpec getStyleForElement(const std::string &type,
|
||||||
|
const std::string &name="", const std::string &parent_type="");
|
||||||
|
|
||||||
v2s32 padding;
|
v2s32 padding;
|
||||||
v2f32 spacing;
|
v2f32 spacing;
|
||||||
@ -574,7 +577,6 @@ private:
|
|||||||
* and the default value for the setting is true.
|
* and the default value for the setting is true.
|
||||||
*/
|
*/
|
||||||
bool m_remap_dbl_click;
|
bool m_remap_dbl_click;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FormspecFormSource: public IFormSource
|
class FormspecFormSource: public IFormSource
|
||||||
|
Loading…
Reference in New Issue
Block a user