Skip to content

Commit

Permalink
[SUTK] Added support for [Float] and [String] Types in Theme Model De…
Browse files Browse the repository at this point in the history
…finition and Theme Definition files
ravi688 committed Dec 15, 2024
1 parent dafde1c commit 66d5534
Showing 7 changed files with 151 additions and 7 deletions.
2 changes: 1 addition & 1 deletion dependencies/Common
46 changes: 40 additions & 6 deletions sutk/include/sutk/ThemeManager.hpp
Original file line number Diff line number Diff line change
@@ -24,13 +24,17 @@ namespace SUTK
{
Color,
Image,
Font
Font,
Float,
String
};
typedef com::Event<com::no_publish_ptr_t> EventType;
typedef EventType::SubscriptionID EventHandlerID;
typedef EventHandlerID BindID;
static constexpr BindID InvalidBindID = EventType::InvalidSubscriptionID;
typedef com::Event<com::no_publish_ptr_t> OnThemeChangeEvent;
template<typename ValueType>
using ValueChangeCallback = std::function<void(const ValueType&)>;
private:
com::unordered_map<KeyType, std::pair<Type, EventType>, KeyViewType> m_defs;
Theme<KeyType, KeyViewType>* m_currentTheme;
@@ -42,10 +46,10 @@ namespace SUTK
void undefine(const KeyViewType& key) noexcept;
Type getType(const KeyViewType& key) noexcept;
template<typename ValueType>
EventHandlerID bind(const KeyViewType& key, std::function<void(ValueType&)> callback) noexcept;
EventHandlerID bind(const KeyViewType& key, ValueChangeCallback<ValueType> callback) noexcept;
void unbind(const KeyViewType& key, EventHandlerID id) noexcept;
template<typename ValueType>
ValueType& getValue(Type type, const KeyViewType& key) noexcept;
const ValueType& getValue(Type type, const KeyViewType& key) noexcept;
void applyTheme(Theme<KeyType, KeyViewType>* theme) noexcept;
Theme<KeyType, KeyViewType>* getCurrentTheme() noexcept { return m_currentTheme; }

@@ -64,6 +68,8 @@ namespace SUTK
com::unordered_map<KeyType, Color4, KeyViewType> m_colors;
com::unordered_map<KeyType, UIDriver::ImageReference, KeyViewType> m_images;
com::unordered_map<KeyType, UIDriver::FontReference, KeyViewType> m_fonts;
com::unordered_map<KeyType, f32> m_floats;
com::unordered_map<KeyType, std::string> m_strings;
ThemeInterfaceType* m_interface;
public:
Theme(UIDriver& driver, ThemeInterfaceType* interface) noexcept : UIDriverObject(driver), m_interface(interface) { }
@@ -94,10 +100,24 @@ namespace SUTK
else
m_fonts.insert({ KeyType { key }, std::forward<UIDriver::FontReference&&>(value) });
}
else if constexpr(std::is_same_v<ValueType, f32>)
{
if(m_interface->getType(key) != ThemeInterfaceType::Type::Float)
DEBUG_LOG_ERROR("Type mismatch");
else
m_floats.insert({ KeyType { key }, std::forward<f32&&>(value) });
}
else if constexpr(std::is_same_v<ValueType, std::string>)
{
if(m_interface->getType(key) != ThemeInterfaceType::Type::String)
DEBUG_LOG_ERROR("Type mismatch");
else
m_strings.insert({ KeyType { key }, std::forward<std::string&&>(value) });
}
else
static_assert(false, "Type not supported");
}
template<typename ValueType>
template<typename ValueType> requires(std::same_as<ValueType, std::string>)
void add(const KeyViewType& key, std::string_view view) noexcept
{
if(view.ends_with(".png") || view.ends_with(".jpg") || view.ends_with(".bmp"))
@@ -122,6 +142,10 @@ namespace SUTK
result = com::find_erase(m_images, key);
else if constexpr(std::is_same_v<ValueType, UIDriver::FontReference>)
result = com::find_erase(m_fonts, key);
else if constexpr(std::is_same_v<ValueType, f32>)
result = com::find_erase(m_floats, key);
else if constexpr(std::is_same_v<ValueType, std::string>)
result = com::find_erase(m_strings, key);
else
static_assert(false, "Type not supported");
_com_assert(result);
@@ -135,6 +159,10 @@ namespace SUTK
return com::find_value(m_images, key);
else if constexpr(std::is_same_v<ValueType, UIDriver::FontReference>)
return com::find_value(m_fonts, key);
else if constexpr(std::is_same_v<ValueType, f32>)
return com::find_value(m_floats, key);
else if constexpr(std::is_same_v<ValueType, std::string>)
return com::find_value(m_strings, key);
else
static_assert(false, "Type not supported");
}
@@ -152,6 +180,10 @@ namespace SUTK
m_defs.insert({ KeyType { key }, { Type::Image, { } } });
else if constexpr(std::is_same_v<ValueType, UIDriver::FontReference>)
m_defs.insert({ KeyType { key }, { Type::Font, { } } });
else if constexpr(std::is_same_v<ValueType, f32>)
m_defs.insert({ KeyType { key }, { Type::Float, { } } });
else if constexpr(std::is_same_v<ValueType, std::string>)
m_defs.insert({ KeyType { key }, { Type::String, { } } });
else
static_assert(false, "Type not supported");
}
@@ -170,7 +202,7 @@ namespace SUTK

template<typename KeyType, com::ViewType<KeyType> KeyViewType>
template<typename ValueType>
ThemeInterface<KeyType, KeyViewType>::EventHandlerID ThemeInterface<KeyType, KeyViewType>::bind(const KeyViewType& key, std::function<void(ValueType&)> callback) noexcept
ThemeInterface<KeyType, KeyViewType>::EventHandlerID ThemeInterface<KeyType, KeyViewType>::bind(const KeyViewType& key, ValueChangeCallback<ValueType> callback) noexcept
{
auto& value = com::find_value(m_defs, key);
auto fn = [_callback = std::move(callback), key, this]()
@@ -191,7 +223,7 @@ namespace SUTK

template<typename KeyType, com::ViewType<KeyType> KeyViewType>
template<typename ValueType>
ValueType& ThemeInterface<KeyType, KeyViewType>::getValue(Type type, const KeyViewType& key) noexcept
const ValueType& ThemeInterface<KeyType, KeyViewType>::getValue(Type type, const KeyViewType& key) noexcept
{
return m_currentTheme->template getValue<ValueType>(key);
}
@@ -222,6 +254,8 @@ namespace SUTK
case Type::Color: stream << "Color"; break;
case Type::Image: stream << "Image"; break;
case Type::Font: stream << "Font"; break;
case Type::Float: stream << "Float"; break;
case Type::String: stream << "String"; break;
}
stream << "\n";
}
71 changes: 71 additions & 0 deletions sutk/source/ThemeManager.cpp
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

#include <common/string.h> // for com_safe_strncmp()
#include <common/debug.h> // for DEBUG_LOG_ERROR()
#include <common/utility.h> // for com_verify_float_str()
#include <disk_manager/file_reader.h> // for load_text_from_file()
#include <phymac_parser/v3d_generic.h> // for ppsr_v3d_generic_parse()

@@ -86,6 +87,18 @@ namespace SUTK
interface->define<UIDriver::FontReference>(nameSV);
continue;
}
typeAttr = node_find_attribute(child, str, "Float");
if(typeAttr)
{
interface->define<f32>(nameSV);
continue;
}
typeAttr = node_find_attribute(child, str, "String");
if(typeAttr)
{
interface->define<std::string>(nameSV);
continue;
}
DEBUG_LOG_WARNING("Type either isn't recognized or not given, skipping \"%.*s\"", nameSV.length(), nameSV.data());
}
ppsr_v3d_generic_parse_result_destroy(NULL, result);
@@ -265,6 +278,52 @@ namespace SUTK
return font;
}

template<>
template<>
f32 ThemeManager<std::string, std::string_view>::deriveValue<f32>(v3d_generic_node_t* node, const char* str) noexcept
{
// Followings are the possibilies:
// 1. 2.4f
// 2. 2.4
// 2. 24
f32 flt = 0;
if(node->qualifier_count == 1)
{
u32_pair_t pair = node->qualifiers[0];
auto len = U32_PAIR_DIFF(pair);
char buffer[len + 1];
memcpy(buffer, pair.start + str, len);
buffer[len] = 0;
if(!com_verify_float_str(buffer))
{
DEBUG_LOG_ERROR("Float value %*.s seems invalid, using 0 as default", len, pair.start + str);
flt = 0;
}
else
flt = std::strtof(buffer, NULL);
}
else
DEBUG_LOG_ERROR("No value is provided");
return flt;
}

template<>
template<>
std::string ThemeManager<std::string, std::string_view>::deriveValue<std::string>(v3d_generic_node_t* node, const char* str) noexcept
{
// Followings are the possibilies:
// 1. "some string here"
// 2. ""
if(node->qualifier_count == 1)
{
u32_pair_t pair = node->qualifiers[0];
return std::string { std::string_view { pair.start + str, U32_PAIR_DIFF(pair) } };
}
else
DEBUG_LOG_ERROR("No value is provided");
return std::string { };
}

template<>
typename ThemeManager<std::string, std::string_view>::ThemeType* ThemeManager<std::string, std::string_view>::loadTheme(const std::string_view filePath) noexcept
{
@@ -374,6 +433,18 @@ namespace SUTK
theme->add<UIDriver::FontReference>(nameSV, std::move(font));
break;
}
case ThemeInterfaceType::Type::Float:
{
f32 flt = deriveValue<f32>(child->value, str);
theme->add<f32>(nameSV, std::move(flt));
break;
}
case ThemeInterfaceType::Type::String:
{
std::string stdstr = deriveValue<std::string>(child->value, str);
theme->add<std::string>(nameSV, std::move(stdstr));
break;
}
default:
{
DEBUG_LOG_WARNING("Type either isn't recognized or not given, skipping \"%.*s\"", nameSV.length(), nameSV.data());
27 changes: 27 additions & 0 deletions sutk/source/tests/ThemeLoadTest.cpp
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
#include <sutk/RenderableContainer.hpp>
#include <sutk/FullWindowContainer.hpp>
#include <sutk/ThemeManager.hpp>
#include <sutk/Label.hpp>

namespace SUTK
{
@@ -73,6 +74,32 @@ namespace SUTK
themeInt->bind<Color4>("LargeButton.HoverColor", std::bind(&RenderRectFill::setColor, renderRect2, std::placeholders::_1));
renderRect2->setColor(Color4::red());

RenderableContainer* renderRectContainer3 = m_uiDriver->createContainer<RenderableContainer>(rootContainer);
RenderRectFill* renderRect3 = m_uiDriver->createRenderable<RenderRectFill>(renderRectContainer3);
renderRectContainer3->setRect({ 11.0f, 10.0f, 5.0f, 5.0f });
AnchorRect* anchor3 = renderRectContainer3->getAnchorRect();
anchor3->setTopLeft({ 0.0f, 0.0f });
anchor3->setBottomRight({ 1.0f, 1.0f });
themeInt->bind<f32>("AnotherButton.AlphaValue", [renderRect3](f32 value) noexcept
{
auto color = renderRect3->getColor();
std::cout << "Float value: " << value << std::endl;
color.alpha(value * 255);
renderRect3->setColor(color);
});
renderRect3->setColor(Color4::yellow());

Label* label = m_uiDriver->createContainer<Label>(rootContainer);
label->setRect({ 11.0f, 8.0f, 5.0f, 5.0f });
AnchorRect* anchor4 = label->getAnchorRect();
anchor4->setTopLeft({ 0.0f, 0.0f });
anchor4->setBottomRight({ 1.0f, 1.0f });
themeInt->bind<std::string>("Label.Value", [label](const std::string& value) noexcept
{
std::cout << "String value: " << value << std::endl;
label->set(value);
});

themeInt->applyTheme(theme1);

m_inputDriver->getOnKeyEvent().subscribe([themeInt, theme1, theme2](IInputDriver* driver, KeyCode keycode, KeyEvent event, ModifierKeys)
4 changes: 4 additions & 0 deletions sutk/themes/model.tmdl
Original file line number Diff line number Diff line change
@@ -19,4 +19,8 @@ ThemeModel
Folder.Open.VG;
[Image]
Folder.Close;
[Float]
AnotherButton.AlphaValue;
[String]
Label.Value;
}
4 changes: 4 additions & 0 deletions sutk/themes/theme1.theme
Original file line number Diff line number Diff line change
@@ -11,4 +11,8 @@ Theme
Folder.Open = "../textures/Thalita-Torres-Office-Archive-folders.512.png";
Folder.Open.VG = "svg_files/close-cross-symbol-in-a-circle-svgrepo-com.svg";
Folder.Close = "icons/Folder-Close.png";
[Float]
AnotherButton.AlphaValue = 0.7f;
[String]
Label.Value = "Hello World From Theme 1";
}
4 changes: 4 additions & 0 deletions sutk/themes/theme2.theme
Original file line number Diff line number Diff line change
@@ -11,4 +11,8 @@ Theme
Folder.Open = "../textures/Smile.bmp";
Folder.Open.VG = "svg_files/apple-svgrepo-com.svg";
Folder.Close = "icons/Folder-Close.png";
[Float]
AnotherButton.AlphaValue = 0.05f;
[String]
Label.Value = "Hello World From Theme 2";
}

0 comments on commit 66d5534

Please sign in to comment.