Added more qualifiers to the Stylesheet system

This commit is contained in:
OmniaX-Dev 2026-04-05 04:52:16 +02:00
parent aebf9c1d14
commit 234aa60ddd
6 changed files with 105 additions and 35 deletions

View file

@ -30,8 +30,23 @@ window.backgroundColor = Color(rgba(40, 0, 0, 255))
borderColor = Color(rgb(0, 255, 0)) borderColor = Color(rgb(0, 255, 0))
} }
(label:pressed) {
textColor = Color(#FF0000FF)
}
(@testLabel label:hover) { (@testLabel label:hover) {
borderColor = $color2 borderColor = $color2
} }
(@testLabel label:pressed) {
backgroundColor = Color(#0040AAFF)
textColor = Color(#505050FF)
}
(label:disabled) {
backgroundColor = Color(#EEEEEEFF)
textColor = Color(#505050FF)
borderColor = Color(#000000FF)
}
% =================================================== % ===================================================

View file

@ -333,6 +333,29 @@ namespace ogfx
} }
} }
void Widget::setThemeQualifier(const ostd::String& qualifier, bool value)
{
for (auto& [name, state] : m_qualifierList)
{
if (name == qualifier)
{
state = value;
reloadTheme();
return;
}
}
}
bool Widget::getThemeQualifier(const ostd::String& qualifier)
{
for (auto& [name, state] : m_qualifierList)
{
if (name == qualifier)
return state;
}
return false;
}
void Widget::__draw(ogfx::BasicRenderer2D& gfx) void Widget::__draw(ogfx::BasicRenderer2D& gfx)
{ {
if (isDrawBoxEnabled()) if (isDrawBoxEnabled())
@ -351,6 +374,7 @@ namespace ogfx
void Widget::__onMousePressed(const Event& event) void Widget::__onMousePressed(const Event& event)
{ {
setThemeQualifier("pressed");
if (hasChildren()) if (hasChildren())
m_widgets.onMousePressed(event); m_widgets.onMousePressed(event);
if (!event.isHandled()) if (!event.isHandled())
@ -364,6 +388,7 @@ namespace ogfx
void Widget::__onMouseReleased(const Event& event) void Widget::__onMouseReleased(const Event& event)
{ {
setThemeQualifier("pressed", false);
m_pressedButton = ogfx::MouseEventData::eButton::None; m_pressedButton = ogfx::MouseEventData::eButton::None;
if (hasChildren()) if (hasChildren())
m_widgets.onMouseReleased(event); m_widgets.onMouseReleased(event);
@ -389,8 +414,7 @@ namespace ogfx
void Widget::__onMouseEntered(const Event& event) void Widget::__onMouseEntered(const Event& event)
{ {
m_qualifier = "hover"; setThemeQualifier("hover");
reloadTheme();
if (callback_onMouseEntered) if (callback_onMouseEntered)
callback_onMouseEntered(event); callback_onMouseEntered(event);
onMouseEntered(event); onMouseEntered(event);
@ -398,8 +422,7 @@ namespace ogfx
void Widget::__onMouseExited(const Event& event) void Widget::__onMouseExited(const Event& event)
{ {
m_qualifier = ""; setThemeQualifier("hover", false);
reloadTheme();
if (callback_onMouseExited) if (callback_onMouseExited)
callback_onMouseExited(event); callback_onMouseExited(event);
onMouseExited(event); onMouseExited(event);
@ -528,7 +551,7 @@ namespace ogfx
void RootWidget::applyTheme(const ostd::Stylesheet& theme) void RootWidget::applyTheme(const ostd::Stylesheet& theme)
{ {
m_color = theme.get<ostd::Color>("window.backgroundColor", getWindow().getClearColor(), getThemeID(), getThemeQualifier()); m_color = theme.get<ostd::Color>("window.backgroundColor", getWindow().getClearColor(), getThemeID(), getThemeQualifierList());
} }
void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx) void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx)
@ -552,15 +575,15 @@ namespace ogfx
void Label::applyTheme(const ostd::Stylesheet& theme) void Label::applyTheme(const ostd::Stylesheet& theme)
{ {
setColor(theme.get<ostd::Color>("label.textColor", ostd::Colors::White, getThemeID(), getThemeQualifier())); setColor(theme.get<ostd::Color>("label.textColor", ostd::Colors::White, getThemeID(), getThemeQualifierList()));
setBackGroundColor(theme.get<ostd::Color>("label.backgroundColor", ostd::Colors::Transparent, getThemeID(), getThemeQualifier())); setBackGroundColor(theme.get<ostd::Color>("label.backgroundColor", ostd::Colors::Transparent, getThemeID(), getThemeQualifierList()));
setFontSize(theme.get<int32_t>("label.fontSize", 20, getThemeID(), getThemeQualifier())); setFontSize(theme.get<int32_t>("label.fontSize", 20, getThemeID(), getThemeQualifierList()));
m_borderRadius = theme.get<int32_t>("label.borderRadius", 10, getThemeID(), getThemeQualifier()); m_borderRadius = theme.get<int32_t>("label.borderRadius", 10, getThemeID(), getThemeQualifierList());
m_borderWidth = theme.get<int32_t>("label.borderWidth", 2, getThemeID(), getThemeQualifier()); m_borderWidth = theme.get<int32_t>("label.borderWidth", 2, getThemeID(), getThemeQualifierList());
m_showBorder = theme.get<bool>("label.showBorder", false, getThemeID(), getThemeQualifier()); m_showBorder = theme.get<bool>("label.showBorder", false, getThemeID(), getThemeQualifierList());
m_borderColor = theme.get<ostd::Color>("label.borderColor", ostd::Colors::White, getThemeID(), getThemeQualifier()); m_borderColor = theme.get<ostd::Color>("label.borderColor", ostd::Colors::White, getThemeID(), getThemeQualifierList());
enableBackground(theme.get<bool>("label.showBackground", false, getThemeID(), getThemeQualifier())); enableBackground(theme.get<bool>("label.showBackground", false, getThemeID(), getThemeQualifierList()));
setPadding(theme.get<ostd::Rectangle>("label.padding", { 5, 5, 5, 5 }, getThemeID(), getThemeQualifier())); setPadding(theme.get<ostd::Rectangle>("label.padding", { 5, 5, 5, 5 }, getThemeID(), getThemeQualifierList()));
} }
void Label::onDraw(ogfx::BasicRenderer2D& gfx) void Label::onDraw(ogfx::BasicRenderer2D& gfx)

View file

@ -88,6 +88,9 @@ namespace ogfx
virtual void applyTheme(const ostd::Stylesheet& theme) = 0; virtual void applyTheme(const ostd::Stylesheet& theme) = 0;
void addThemeOverride(const ostd::String& key, ostd::Stylesheet::TypeVariant value, const ostd::String& themeID = "", const ostd::String& qualifier = "", bool propagate = true); void addThemeOverride(const ostd::String& key, ostd::Stylesheet::TypeVariant value, const ostd::String& themeID = "", const ostd::String& qualifier = "", bool propagate = true);
void reloadTheme(void); void reloadTheme(void);
void setThemeQualifier(const ostd::String& qualifier, bool value = true);
bool getThemeQualifier(const ostd::String& qualifier);
inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; }
inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { } inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { }
inline virtual void onUpdate(void) { } inline virtual void onUpdate(void) { }
@ -154,7 +157,6 @@ namespace ogfx
inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; } inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; }
inline ostd::String getThemeID(void) const { return m_themeID; } inline ostd::String getThemeID(void) const { return m_themeID; }
inline void setThemeID(const ostd::String& id) { m_themeID = id; } inline void setThemeID(const ostd::String& id) { m_themeID = id; }
inline ostd::String getThemeQualifier(void) const { return m_qualifier; }
protected: protected:
inline void disableChildren(void) { m_allowChildren = false; } inline void disableChildren(void) { m_allowChildren = false; }
@ -193,7 +195,13 @@ namespace ogfx
MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None }; MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None };
ostd::String m_themeID { "" }; ostd::String m_themeID { "" };
ostd::String m_qualifier { "" }; ostd::Stylesheet::QualifierList m_qualifierList {
{ "disabled", false },
{ "pressed", false },
{ "hover", false },
{ "focused", false },
{ "active", false }
};
std::vector<ThemeOverride> m_themeOverrides; std::vector<ThemeOverride> m_themeOverrides;
bool m_drawBox { true }; bool m_drawBox { true };

View file

@ -34,16 +34,17 @@ namespace ostd
return *this; return *this;
} }
Stylesheet& Stylesheet::loadFromFile(const ostd::String& filePath) Stylesheet& Stylesheet::loadFromFile(const ostd::String& filePath, bool clearCurrentRules)
{ {
ostd::String outContent = ""; ostd::String outContent = "";
ostd::FileSystem::readTextFileRaw(filePath, outContent); ostd::FileSystem::readTextFileRaw(filePath, outContent);
return loadFromString(outContent, filePath); return loadFromString(outContent, filePath, clearCurrentRules);
} }
Stylesheet& Stylesheet::loadFromString(const ostd::String& content, const ostd::String& filePath) Stylesheet& Stylesheet::loadFromString(const ostd::String& content, const ostd::String& filePath, bool clearCurrentRules)
{ {
if (clearCurrentRules)
m_values.clear();
std::vector<ostd::String> lines = content.tokenize("\n", false, true).getRawData(); std::vector<ostd::String> lines = content.tokenize("\n", false, true).getRawData();
uint32_t lineNumber = 0; uint32_t lineNumber = 0;
ostd::String lineCopy = ""; ostd::String lineCopy = "";
@ -121,7 +122,6 @@ namespace ostd
} }
ostd::String rawSelector = line.new_substr(1, line.indexOf(")")).trim(); ostd::String rawSelector = line.new_substr(1, line.indexOf(")")).trim();
groupSelector = parseGroupSelector(rawSelector); groupSelector = parseGroupSelector(rawSelector);
std::cout << groupSelector << "\n";
if (line.contains("{")) if (line.contains("{"))
{ {
line.substr(line.indexOf("{")).trim(); line.substr(line.indexOf("{")).trim();
@ -151,31 +151,43 @@ namespace ostd
m_values[fullKey] = std::move(value); m_values[fullKey] = std::move(value);
} }
const Stylesheet::TypeVariant* Stylesheet::getVariant(const ostd::String& key, const ostd::String& themeID, const ostd::String& qualifier) const const Stylesheet::TypeVariant* Stylesheet::getVariant(const ostd::String& key, const ostd::String& themeID, const QualifierList& qualifierList) const
{ {
if (auto v = getFull("@" + themeID + ":" + qualifier + "." + key)) for (const auto&[qualifier, state] : qualifierList)
{ {
return v; const TypeVariant* v = (state ? getFull("@" + themeID + ":" + qualifier + "." + key) : nullptr);
// std::cout << "0: " << "@" + themeID + ":" + qualifier + "." + key << "\n";
if (v)
{
std::cout << "1: " << "@" + themeID + ":" + qualifier + "." + key << "\n";
return v;
}
v = (state ? getFull("@:" + qualifier + "." + key) : nullptr);
if (v)
{
std::cout << "2: " << "@:" + qualifier + "." + key << "\n";
return v;
}
} }
else if (auto v = getFull("@:" + qualifier + "." + key)) if (auto v = getFull("@" + themeID + "." + key))
{
return v;
}
else if (auto v = getFull("@" + themeID + "." + key))
{ {
std::cout << "3: " << "@" + themeID + "." + key << "\n";
return v; return v;
} }
else if (auto v = getFull("@." + key)) else if (auto v = getFull("@." + key))
{ {
std::cout << "4: " << "@." + key << "\n";
return v; return v;
} }
std::cout << "\n\n";
return nullptr; return nullptr;
} }
const Stylesheet::TypeVariant* Stylesheet::getFull(const ostd::String& fullKey) const const Stylesheet::TypeVariant* Stylesheet::getFull(const ostd::String& fullKey) const
{ {
// std::cout << " GET: " << key << "\n";
auto it = m_values.find(fullKey); auto it = m_values.find(fullKey);
// if (it != m_values.end())
// std::cout << " GET: " << fullKey << "\n";
return it != m_values.end() ? &it->second : nullptr; return it != m_values.end() ? &it->second : nullptr;
} }
@ -286,4 +298,12 @@ namespace ostd
newLines.push_back(selector.new_add(".").new_add(property)); newLines.push_back(selector.new_add(".").new_add(property));
return newLines; return newLines;
} }
void Stylesheet::debugPrint(void)
{
for (const auto&[key, value] : m_values)
{
std::cout << key << "\n";
}
}
} }

View file

@ -29,21 +29,22 @@ namespace ostd
{ {
class Stylesheet class Stylesheet
{ {
public: using QualifierList = std::vector<std::pair<const ostd::String, bool>>;
public: using TypeVariant = std::variant<int32_t, float, bool, ostd::String, ostd::Color, ostd::Rectangle, ostd::Vec2>; public: using TypeVariant = std::variant<int32_t, float, bool, ostd::String, ostd::Color, ostd::Rectangle, ostd::Vec2>;
public: public:
Stylesheet(void); Stylesheet(void);
Stylesheet& clear(void); Stylesheet& clear(void);
Stylesheet& loadFromFile(const ostd::String& filePath); Stylesheet& loadFromFile(const ostd::String& filePath, bool clearCurrentRules = true);
Stylesheet& loadFromString(const ostd::String& content, const ostd::String& filePath = "memory://"); Stylesheet& loadFromString(const ostd::String& content, const ostd::String& filePath = "memory://", bool clearCurrentRules = true);
void set(const std::string& key, TypeVariant value, const ostd::String& themeID); void set(const std::string& key, TypeVariant value, const ostd::String& themeID);
void setFull(const ostd::String& fullKey, TypeVariant value); void setFull(const ostd::String& fullKey, TypeVariant value);
const TypeVariant* getVariant(const ostd::String& key, const ostd::String& themeID, const ostd::String& qualifier) const; const TypeVariant* getVariant(const ostd::String& key, const ostd::String& themeID, const QualifierList& qualifierList) const;
const TypeVariant* getFull(const ostd::String& fullKey) const; const TypeVariant* getFull(const ostd::String& fullKey) const;
template<typename T> template<typename T>
inline T get(const ostd::String& key, const T& fallback, const ostd::String& themeID, const ostd::String& qualifier) const inline T get(const ostd::String& key, const T& fallback, const ostd::String& themeID, const QualifierList& qualifierList) const
{ {
if (auto v = getVariant(key, themeID, qualifier)) if (auto v = getVariant(key, themeID, qualifierList))
{ {
if (auto p = std::get_if<T>(v)) if (auto p = std::get_if<T>(v))
return *p; return *p;
@ -51,6 +52,8 @@ namespace ostd
return fallback; return fallback;
} }
void debugPrint(void);
private: private:
bool parseThemeFileLine(const ostd::String& line); bool parseThemeFileLine(const ostd::String& line);
ostd::String parseGroupSelector(const ostd::String& rawSelector) const; ostd::String parseGroupSelector(const ostd::String& rawSelector) const;

View file

@ -63,6 +63,7 @@ class Window : public ogfx::gui::Window
// m_label1.applyThemeValue(m_theme, "label.backgroundColor", ostd::Colors::DarkGreen, false); // m_label1.applyThemeValue(m_theme, "label.backgroundColor", ostd::Colors::DarkGreen, false);
// }); // });
addWidget(m_label1); addWidget(m_label1);
m_label1.setThemeQualifier("disabled");
m_label2.setPosition(100, 400); m_label2.setPosition(100, 400);
m_label2.setText("Ciccia Bella!"); m_label2.setText("Ciccia Bella!");