/* OmniaFramework - A collection of useful functionality Copyright (C) 2026 OmniaX-Dev This file is part of OmniaFramework. OmniaFramework is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OmniaFramework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OmniaFramework. If not, see . */ #pragma once #include #include #include #include #include #include namespace ostd { class Stylesheet { public: using QualifierList = stdvec>; public: using VariableList = stdumap>; public: using TypeVariant = std::variant; private: struct Macro { String body { "" }; stdvec> params; inline i32 argCount(void) const { return params.size(); } }; public: Stylesheet(void); Stylesheet& clear(void); Stylesheet& loadFromFile(const String& filePath, bool clearCurrentRules = true, VariableList variables = {}); Stylesheet& loadFromString(const String& content, const String& filePath = "memory://", bool clearCurrentRules = true, VariableList variables = {}); void set(const std::string& key, TypeVariant value, const String& themeID); void removeRule(const String& fullKey); void setFull(const String& fullKey, TypeVariant value); const TypeVariant* getVariant(const String& key, const stdvec& themeIDList, const QualifierList& qualifierList) const; const TypeVariant* getFull(const String& fullKey) const; template inline T get(const String& key, const T& fallback, const stdvec& themeIDList, const QualifierList& qualifierList) const { if (auto v = getVariant(key, themeIDList, qualifierList)) { // Direct match: return as-is if (auto p = std::get_if(v)) return *p; // Cross-cast for numeric types if constexpr (std::is_same_v) { if (auto p = std::get_if(v)) return cast(*p); } else if constexpr (std::is_same_v) { if (auto p = std::get_if(v)) return cast(*p); } } return fallback; } void debugPrint(void); String typeVariantToString(const TypeVariant& v); private: bool parseThemeFileLine(const String& line, const VariableList& variables, bool exitCondition = false); String parseGroupSelector(const String& rawSelector) const; stdvec parseGroup(const String& selector, const stdvec& group); Color parseColor(const String& _value, const VariableList& variables); Vec2 parseVec2(const String& _value, const VariableList& variables); Rectangle parseRect(const String& _value, const VariableList& variables); ColorGradient parseColorGradient(const String& _value, const VariableList& variables); AnimationData parseAnim(const String& _value, bool& outError, const VariableList& variables); String replaceVariables(const String& line, const VariableList& variables, bool stop_at_first_match = true); bool parseMacro(const String& macroCode); stdvec parseMacroCall(const String& call, const Macro& macro); private: stdumap m_values; stdumap m_macros; const String m_validNameRegex { "^[A-Za-z_][A-Za-z0-9_]*$" }; inline static const String MacroParamDefault { "NO_VAL" }; }; }