]> git.lizzy.rs Git - minetest.git/blobdiff - src/gui/StyleSpec.h
Translated using Weblate (Malay)
[minetest.git] / src / gui / StyleSpec.h
index 999c1d2379d6b196de6643dd3d8317cb7e6a00b2..7a45e07d129f5ac7a98a4a6253d0ca78b66143dd 100644 (file)
@@ -18,9 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "client/tile.h" // ITextureSource
+#include "client/fontengine.h"
+#include "debug.h"
 #include "irrlichttypes_extrabloated.h"
 #include "util/string.h"
+#include <algorithm>
 #include <array>
+#include <vector>
 
 #pragma once
 
@@ -31,25 +35,45 @@ class StyleSpec
        {
                TEXTCOLOR,
                BGCOLOR,
-               BGCOLOR_HOVERED,
-               BGCOLOR_PRESSED,
+               BGCOLOR_HOVERED, // Note: Deprecated property
+               BGCOLOR_PRESSED, // Note: Deprecated property
                NOCLIP,
                BORDER,
                BGIMG,
-               BGIMG_HOVERED,
+               BGIMG_HOVERED, // Note: Deprecated property
                BGIMG_MIDDLE,
-               BGIMG_PRESSED,
+               BGIMG_PRESSED, // Note: Deprecated property
                FGIMG,
-               FGIMG_HOVERED,
-               FGIMG_PRESSED,
+               FGIMG_HOVERED, // Note: Deprecated property
+               FGIMG_MIDDLE,
+               FGIMG_PRESSED, // Note: Deprecated property
                ALPHA,
+               CONTENT_OFFSET,
+               PADDING,
+               FONT,
+               FONT_SIZE,
+               COLORS,
+               BORDERCOLORS,
+               BORDERWIDTHS,
+               SOUND,
+               SPACING,
+               SIZE,
                NUM_PROPERTIES,
                NONE
        };
+       enum State
+       {
+               STATE_DEFAULT = 0,
+               STATE_HOVERED = 1 << 0,
+               STATE_PRESSED = 1 << 1,
+               NUM_STATES = 1 << 2,
+               STATE_INVALID = 1 << 3,
+       };
 
 private:
        std::array<bool, NUM_PROPERTIES> property_set{};
        std::array<std::string, NUM_PROPERTIES> properties;
+       State state_map = STATE_DEFAULT;
 
 public:
        static Property GetPropertyByName(const std::string &name)
@@ -78,10 +102,32 @@ class StyleSpec
                        return FGIMG;
                } else if (name == "fgimg_hovered") {
                        return FGIMG_HOVERED;
+               } else if (name == "fgimg_middle") {
+                       return FGIMG_MIDDLE;
                } else if (name == "fgimg_pressed") {
                        return FGIMG_PRESSED;
                } else if (name == "alpha") {
                        return ALPHA;
+               } else if (name == "content_offset") {
+                       return CONTENT_OFFSET;
+               } else if (name == "padding") {
+                       return PADDING;
+               } else if (name == "font") {
+                       return FONT;
+               } else if (name == "font_size") {
+                       return FONT_SIZE;
+               } else if (name == "colors") {
+                       return COLORS;
+               } else if (name == "bordercolors") {
+                       return BORDERCOLORS;
+               } else if (name == "borderwidths") {
+                       return BORDERWIDTHS;
+               } else if (name == "sound") {
+                       return SOUND;
+               } else if (name == "spacing") {
+                       return SPACING;
+               } else if (name == "size") {
+                       return SIZE;
                } else {
                        return NONE;
                }
@@ -99,6 +145,49 @@ class StyleSpec
                property_set[prop] = true;
        }
 
+       //! Parses a name and returns the corresponding state enum
+       static State getStateByName(const std::string &name)
+       {
+               if (name == "default") {
+                       return STATE_DEFAULT;
+               } else if (name == "hovered") {
+                       return STATE_HOVERED;
+               } else if (name == "pressed") {
+                       return STATE_PRESSED;
+               } else {
+                       return STATE_INVALID;
+               }
+       }
+
+       //! Gets the state that this style is intended for
+       State getState() const
+       {
+               return state_map;
+       }
+
+       //! Set the given state on this style
+       void addState(State state)
+       {
+               FATAL_ERROR_IF(state >= NUM_STATES, "Out-of-bounds state received");
+
+               state_map = static_cast<State>(state_map | state);
+       }
+
+       //! Using a list of styles mapped to state values, calculate the final
+       //  combined style for a state by propagating values in its component states
+       static StyleSpec getStyleFromStatePropagation(const std::array<StyleSpec, NUM_STATES> &styles, State state)
+       {
+               StyleSpec temp = styles[StyleSpec::STATE_DEFAULT];
+               temp.state_map = state;
+               for (int i = StyleSpec::STATE_DEFAULT + 1; i <= state; i++) {
+                       if ((state & i) != 0) {
+                               temp = temp | styles[i];
+                       }
+               }
+
+               return temp;
+       }
+
        video::SColor getColor(Property prop, video::SColor def) const
        {
                const auto &val = properties[prop];
@@ -120,6 +209,42 @@ class StyleSpec
                return color;
        }
 
+       std::array<video::SColor, 4> getColorArray(Property prop,
+               std::array<video::SColor, 4> def) const
+       {
+               const auto &val = properties[prop];
+               if (val.empty())
+                       return def;
+
+               std::vector<std::string> strs;
+               if (!parseArray(val, strs))
+                       return def;
+
+               for (size_t i = 0; i <= 3; i++) {
+                       video::SColor color;
+                       if (parseColorString(strs[i], color, false, 0xff))
+                               def[i] = color;
+               }
+
+               return def;
+       }
+
+       std::array<s32, 4> getIntArray(Property prop, std::array<s32, 4> def) const
+       {
+               const auto &val = properties[prop];
+               if (val.empty())
+                       return def;
+
+               std::vector<std::string> strs;
+               if (!parseArray(val, strs))
+                       return def;
+
+               for (size_t i = 0; i <= 3; i++)
+                       def[i] = stoi(strs[i]);
+
+               return def;
+       }
+
        irr::core::rect<s32> getRect(Property prop, irr::core::rect<s32> def) const
        {
                const auto &val = properties[prop];
@@ -143,6 +268,83 @@ class StyleSpec
                return rect;
        }
 
+       v2f32 getVector2f(Property prop, v2f32 def) const
+       {
+               const auto &val = properties[prop];
+               if (val.empty())
+                       return def;
+
+               v2f32 vec;
+               if (!parseVector2f(val, &vec))
+                       return def;
+
+               return vec;
+       }
+
+       v2s32 getVector2i(Property prop, v2s32 def) const
+       {
+               const auto &val = properties[prop];
+               if (val.empty())
+                       return def;
+
+               v2f32 vec;
+               if (!parseVector2f(val, &vec))
+                       return def;
+
+               return v2s32(vec.X, vec.Y);
+       }
+
+       v2s32 getVector2i(Property prop) const
+       {
+               const auto &val = properties[prop];
+               FATAL_ERROR_IF(val.empty(), "Unexpected missing property");
+
+               v2f32 vec;
+               parseVector2f(val, &vec);
+               return v2s32(vec.X, vec.Y);
+       }
+
+       gui::IGUIFont *getFont() const
+       {
+               FontSpec spec(FONT_SIZE_UNSPECIFIED, FM_Standard, false, false);
+
+               const std::string &font = properties[FONT];
+               const std::string &size = properties[FONT_SIZE];
+
+               if (font.empty() && size.empty())
+                       return nullptr;
+
+               std::vector<std::string> modes = split(font, ',');
+
+               for (size_t i = 0; i < modes.size(); i++) {
+                       if (modes[i] == "normal")
+                               spec.mode = FM_Standard;
+                       else if (modes[i] == "mono")
+                               spec.mode = FM_Mono;
+                       else if (modes[i] == "bold")
+                               spec.bold = true;
+                       else if (modes[i] == "italic")
+                               spec.italic = true;
+               }
+
+               if (!size.empty()) {
+                       int calc_size = 1;
+
+                       if (size[0] == '*') {
+                               std::string new_size = size.substr(1); // Remove '*' (invalid for stof)
+                               calc_size = stof(new_size) * g_fontengine->getFontSize(spec.mode);
+                       } else if (size[0] == '+' || size[0] == '-') {
+                               calc_size = stoi(size) + g_fontengine->getFontSize(spec.mode);
+                       } else {
+                               calc_size = stoi(size);
+                       }
+
+                       spec.size = (unsigned)std::min(std::max(calc_size, 1), 999);
+               }
+
+               return g_fontengine->getFont(spec);
+       }
+
        video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc,
                        video::ITexture *def) const
        {
@@ -203,6 +405,24 @@ class StyleSpec
        }
 
 private:
+       bool parseArray(const std::string &value, std::vector<std::string> &arr) const
+       {
+               std::vector<std::string> strs = split(value, ',');
+
+               if (strs.size() == 1) {
+                       arr = {strs[0], strs[0], strs[0], strs[0]};
+               } else if (strs.size() == 2) {
+                       arr = {strs[0], strs[1], strs[0], strs[1]};
+               } else if (strs.size() == 4) {
+                       arr = strs;
+               } else {
+                       warningstream << "Invalid array size (" << strs.size()
+                                       << " arguments): \"" << value << "\"" << std::endl;
+                       return false;
+               }
+               return true;
+       }
+
        bool parseRect(const std::string &value, irr::core::rect<s32> *parsed_rect) const
        {
                irr::core::rect<s32> rect;
@@ -233,4 +453,27 @@ class StyleSpec
 
                return true;
        }
+
+       bool parseVector2f(const std::string &value, v2f32 *parsed_vec) const
+       {
+               v2f32 vec;
+               std::vector<std::string> v_vector = split(value, ',');
+
+               if (v_vector.size() == 1) {
+                       f32 x = stof(v_vector[0]);
+                       vec.X = x;
+                       vec.Y = x;
+               } else if (v_vector.size() == 2) {
+                       vec.X = stof(v_vector[0]);
+                       vec.Y = stof(v_vector[1]);
+               } else {
+                       warningstream << "Invalid 2d vector string format: \"" << value
+                                       << "\"" << std::endl;
+                       return false;
+               }
+
+               *parsed_vec = vec;
+
+               return true;
+       }
 };