From e2072d257fd75361eb2062a6c928fe0800afdab1 Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Fri, 3 May 2024 15:09:26 +0300 Subject: [PATCH] tmp --- Objects/applications/GUIEntry.cpp | 6 +- Widgets/CMakeLists.txt | 11 +- Widgets/examples/{Entry.cpp => ChatGUI.cpp} | 8 +- .../examples/{ExampleGUI.hpp => ChatGUI.hpp} | 230 +++++++++++++----- Widgets/examples/SimpleGUI.cpp | 50 ++++ Widgets/public/ButtonWidget.hpp | 45 ++-- Widgets/public/LabelWidget.hpp | 35 +-- Widgets/public/ScrollableWidget.hpp | 119 +++++---- Widgets/public/SliderWidget.hpp | 49 ++-- Widgets/public/SplitViewWidget.hpp | 55 +++-- Widgets/public/TextInputWidget.hpp | 42 +++- Widgets/public/WidgetBase.hpp | 56 +---- Widgets/public/WidgetConfig.hpp | 98 -------- Widgets/public/WidgetManager.hpp | 131 ++++++++++ 14 files changed, 594 insertions(+), 341 deletions(-) rename Widgets/examples/{Entry.cpp => ChatGUI.cpp} (74%) rename Widgets/examples/{ExampleGUI.hpp => ChatGUI.hpp} (51%) create mode 100644 Widgets/examples/SimpleGUI.cpp delete mode 100644 Widgets/public/WidgetConfig.hpp create mode 100644 Widgets/public/WidgetManager.hpp diff --git a/Objects/applications/GUIEntry.cpp b/Objects/applications/GUIEntry.cpp index 5b0c4e8..b5c518e 100644 --- a/Objects/applications/GUIEntry.cpp +++ b/Objects/applications/GUIEntry.cpp @@ -6,9 +6,9 @@ using namespace tp; using namespace obj; -class ExampleGUI : public Application { +class SimpleGUI : public Application { public: - ExampleGUI() { gui.cd(objects_api::create(), "root"); } + SimpleGUI() { gui.cd(objects_api::create(), "root"); } void processFrame(EventHandler* eventHandler) override {} @@ -28,7 +28,7 @@ int main() { if (module.initialize()) { { - ExampleGUI gui; + SimpleGUI gui; gui.run(); } module.deinitialize(); diff --git a/Widgets/CMakeLists.txt b/Widgets/CMakeLists.txt index 5047dae..dc1b591 100644 --- a/Widgets/CMakeLists.txt +++ b/Widgets/CMakeLists.txt @@ -10,7 +10,12 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui) ### -------------------------- Applications -------------------------- ### -add_executable(ExampleGui examples/Entry.cpp) -target_link_libraries(ExampleGui ${PROJECT_NAME} ${GLEW_LIB}) -target_include_directories(ExampleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR}) +add_executable(SimpleGui examples/SimpleGUI.cpp) +target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB}) +target_include_directories(SimpleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR}) + +add_executable(ChatGui examples/ChatGUI.cpp) +target_link_libraries(ChatGui ${PROJECT_NAME} ${GLEW_LIB}) +target_include_directories(ChatGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR}) + file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/") \ No newline at end of file diff --git a/Widgets/examples/Entry.cpp b/Widgets/examples/ChatGUI.cpp similarity index 74% rename from Widgets/examples/Entry.cpp rename to Widgets/examples/ChatGUI.cpp index 17a643b..580b979 100644 --- a/Widgets/examples/Entry.cpp +++ b/Widgets/examples/ChatGUI.cpp @@ -1,5 +1,5 @@ -#include "ExampleGUI.hpp" +#include "ChatGUI.hpp" #include "GraphicApplication.hpp" @@ -7,16 +7,20 @@ using namespace tp; class ExampleGUI : public Application { public: - ExampleGUI() = default; + ExampleGUI() { mGui.setupConfig(mWidgetManager); } void processFrame(EventHandler* eventHandler) override { auto rec = RectF({ 0, 0 }, mWindow->getSize()); + + mGui.updateConfigCache(mWidgetManager); + mGui.proc(*eventHandler, rec, rec); } void drawFrame(Canvas* canvas) override { mGui.draw(*canvas); } private: + WidgetManager mWidgetManager; ComplexWidget mGui; }; diff --git a/Widgets/examples/ExampleGUI.hpp b/Widgets/examples/ChatGUI.hpp similarity index 51% rename from Widgets/examples/ExampleGUI.hpp rename to Widgets/examples/ChatGUI.hpp index 474151e..805cd4c 100644 --- a/Widgets/examples/ExampleGUI.hpp +++ b/Widgets/examples/ChatGUI.hpp @@ -7,15 +7,7 @@ namespace tp { template class UserWidget : public Widget { public: - UserWidget() { - this->createConfig("User"); - this->addColor("Base", "Base"); - this->addValue("Size", "FontSize"); - this->addValue("Padding", "Padding"); - this->addColor("ColUser", "Front"); - this->addColor("Accent", "Accent"); - this->addValue("Rounding", "Rounding"); - } + UserWidget() { this->mId = "UserWidget"; } void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override { this->mArea = aArea; @@ -28,34 +20,48 @@ namespace tp { void draw(Canvas& canvas) override { if (!this->mVisible) return; - if (mIsHover) canvas.rect(this->mArea, this->getColor("Accent"), this->getValue("Rounding")); - else canvas.rect(this->mArea, this->getColor("Base"), this->getValue("Rounding")); + if (mIsHover) canvas.rect(this->mArea, mAccentColor, mRounding); + else canvas.rect(this->mArea, mBaseColor, mRounding); - const auto padding = this->getValue("Padding"); - const auto size = this->getValue("Size"); - const auto colUser = this->getColor("ColUser"); + canvas.text(mUser.c_str(), this->mArea, mFontSize, Canvas::CC, mPadding, mUserColor); + } - canvas.text(mUser.c_str(), this->mArea, size, Canvas::CC, padding, colUser); + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Base", "Base"); + wm.addReference(this->mId, "Size", "FontSize"); + wm.addReference(this->mId, "Padding", "Padding"); + wm.addReference(this->mId, "ColUser", "Front"); + wm.addReference(this->mId, "Accent", "Accent"); + wm.addReference(this->mId, "Rounding", "Rounding"); + } + + void updateConfigCache(const WidgetManager& wm) override { + mBaseColor = wm.getColor(this->mId, "Base"); + mFontSize = wm.getNumber(this->mId, "Size"); + mPadding = wm.getNumber(this->mId, "Padding"); + mUserColor = wm.getColor(this->mId, "ColUser"); + mAccentColor = wm.getColor(this->mId, "Accent"); + mRounding = wm.getNumber(this->mId, "Rounding"); } public: std::string mUser = "UserName"; bool mIsHover = false; + + RGBA mBaseColor; + RGBA mUserColor; + RGBA mAccentColor; + halnf mPadding = 0; + halnf mFontSize = 0; + halnf mRounding = 0; }; template class MessageWidget : public Widget { public: - MessageWidget() { - this->createConfig("Message"); - this->addColor("Base", "Base"); - this->addValue("Size", "FontSize"); - this->addValue("SizeUser", "FontSizeDim"); - this->addValue("Padding", "Padding"); - this->addColor("ColUser", "Front"); - this->addColor("Col", "FrontDim"); - this->addValue("Rounding", "Rounding"); - } + MessageWidget() { this->mId = "MessageWidget"; } void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override { this->mArea = aArea; @@ -67,14 +73,7 @@ namespace tp { void draw(Canvas& canvas) override { if (!this->mVisible) return; - - if (mIsHover) canvas.rect(this->mArea, this->getColor("Base"), this->getValue("Rounding")); - - const auto padding = this->getValue("Padding"); - const auto size = this->getValue("Size"); - const auto sizeUser = this->getValue("SizeUser"); - const auto col = this->getColor("Col"); - const auto colUser = this->getColor("ColUser"); + if (mIsHover) canvas.rect(this->mArea, mBaseColor, mRounding); auto userName = this->mArea; userName.w = 25; @@ -83,22 +82,51 @@ namespace tp { content.y = userName.y + userName.w; content.w = this->mArea.w - userName.w; - canvas.text(mContent.c_str(), content, size, Canvas::LC, padding, col); - canvas.text(mUser.c_str(), userName, sizeUser, Canvas::LC, padding, colUser); + canvas.text(mContent.c_str(), content, mFontSize, Canvas::LC, mPadding, mUserColorDim); + canvas.text(mUser.c_str(), userName, mFontSizeDim, Canvas::LC, mPadding, mUserColor); + } + + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Base", "Base"); + wm.addReference(this->mId, "Size", "FontSize"); + wm.addReference(this->mId, "SizeUser", "FontSizeDim"); + wm.addReference(this->mId, "Padding", "Padding"); + wm.addReference(this->mId, "UserColor", "Front"); + wm.addReference(this->mId, "UserColorDim", "FrontDim"); + wm.addReference(this->mId, "Rounding", "Rounding"); + } + + void updateConfigCache(const WidgetManager& wm) override { + mBaseColor = wm.getColor(this->mId, "Base"); + mFontSize = wm.getNumber(this->mId, "Size"); + mFontSizeDim = wm.getNumber(this->mId, "SizeUser"); + mPadding = wm.getNumber(this->mId, "Padding"); + mUserColor = wm.getColor(this->mId, "UserColor"); + mUserColorDim = wm.getColor(this->mId, "UserColorDim"); + mRounding = wm.getNumber(this->mId, "Rounding"); } public: std::string mContent = "Message Content"; std::string mUser = "UserName"; bool mIsHover = false; + + RGBA mBaseColor; + RGBA mUserColor; + RGBA mUserColorDim; + halnf mPadding = 0; + halnf mFontSize = 0; + halnf mFontSizeDim = 0; + halnf mRounding = 0; }; template class LoginWidget : public Widget { public: explicit LoginWidget() { - this->createConfig("Login"); - this->addColor("Back", "Background"); + this->mId = "Login"; + mPass.mId = "pass"; mUser.mId = "user"; mButton.mLabel.mLabel = "Login"; @@ -120,26 +148,45 @@ namespace tp { } void draw(Canvas& canvas) override { - canvas.rect(this->mArea, this->getColor("Back")); + canvas.rect(this->mArea, mBGColor); mButton.draw(canvas); mUser.draw(canvas); mPass.draw(canvas); } + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Back", "Base"); + + mUser.setupConfig(wm); + mPass.setupConfig(wm); + mButton.setupConfig(wm); + } + + void updateConfigCache(const WidgetManager& wm) override { + mBGColor = wm.getColor(this->mId, "Back"); + + mUser.updateConfigCache(wm); + mPass.updateConfigCache(wm); + mButton.updateConfigCache(wm); + } + public: TextInputWidget mUser; TextInputWidget mPass; ButtonWidget mButton; bool mLogged = false; + + RGBA mBGColor; }; template class ActiveChatWidget : public Widget { public: ActiveChatWidget() { - this->createConfig("ActiveChat"); - this->addColor("Back", "Background"); - this->addValue("Padding", "Padding"); + this->mId = "ActiveWidget"; + mSend.mLabel.mLabel = "Send"; mMessage.mId = "Message"; } @@ -152,16 +199,16 @@ namespace tp { auto input = this->mArea; input.y = history.w + 10; - input.w = 40 - this->getValue("Padding"); - input.x += this->getValue("Padding"); - input.z -= this->getValue("Padding"); + input.w = 40 - mPadding; + input.x += mPadding; + input.z -= mPadding; auto inputMessage = input; inputMessage.z -= 100; auto inputSend = input; - inputSend.x = inputMessage.x + inputMessage.z + this->getValue("Padding"); - inputSend.z = 100 - this->getValue("Padding") * 2; + inputSend.x = inputMessage.x + inputMessage.z + mPadding; + inputSend.z = 100 - mPadding * 2; mSend.proc(events, this->mArea, inputSend); mMessage.proc(events, this->mArea, inputMessage); @@ -174,26 +221,53 @@ namespace tp { } void draw(Canvas& canvas) override { - canvas.rect(this->mArea, this->getColor("Back")); + canvas.rect(this->mArea, mBGColor); mHistoryView.draw(canvas); mMessage.draw(canvas); mSend.draw(canvas); } + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + + wm.addReference(this->mId, "Back", "Background"); + wm.addReference(this->mId, "Padding", "Padding"); + + mHistoryView.setupConfig(wm); + mMessage.setupConfig(wm); + mSend.setupConfig(wm); + + MessageWidget().setupConfig(wm); + } + + void updateConfigCache(const WidgetManager& wm) override { + mBGColor = wm.getColor(this->mId, "Back"); + mPadding = wm.getNumber(this->mId, "Padding"); + + mHistoryView.updateConfigCache(wm); + mMessage.updateConfigCache(wm); + mSend.updateConfigCache(wm); + + for (auto message : mMessages) { + message->updateConfigCache(wm); + } + } + public: Buffer> mMessages; ScrollableWindow mHistoryView; TextInputWidget mMessage; ButtonWidget mSend; + + RGBA mBGColor; + halnf mPadding = 0; }; template class ChattingWidget : public Widget { public: ChattingWidget() { - this->createConfig("Chatting"); - this->addColor("Back", "Background"); - this->addValue("Padding", "Padding"); + this->mId = "Chatting"; // todo : fetch code mUsers.append(UserWidget()); @@ -225,34 +299,54 @@ namespace tp { this->mArea = aArea; mSplitView.proc(events, aArea, aArea); - - const auto padding = this->getValue("Padding"); mSideView.proc(events, this->mArea, mSplitView.getSecond()); - mActive.proc(events, aArea, mSplitView.getFirst()); } void draw(Canvas& canvas) override { - canvas.rect(this->mArea, this->getColor("Back")); + canvas.rect(this->mArea, mBGColor); mSplitView.draw(canvas); mSideView.draw(canvas); mActive.draw(canvas); } + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + + wm.addReference(this->mId, "Back", "Background"); + + mSideView.setupConfig(wm); + mActive.setupConfig(wm); + mSplitView.setupConfig(wm); + + UserWidget().setupConfig(wm); + } + + void updateConfigCache(const WidgetManager& wm) override { + mBGColor = wm.getColor(this->mId, "Back"); + + mSideView.updateConfigCache(wm); + mActive.updateConfigCache(wm); + mSplitView.updateConfigCache(wm); + + for (auto user : mUsers) { + user->updateConfigCache(wm); + } + } + public: Buffer> mUsers; ScrollableWindow mSideView; ActiveChatWidget mActive; SplitView mSplitView; + + RGBA mBGColor; }; template class ComplexWidget : public Widget { public: - ComplexWidget() { - this->createConfig("chat"); - this->addColor("Back", "Background"); - } + ComplexWidget() { this->mId = "Chat"; } void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override { this->mArea = aArea; @@ -268,14 +362,32 @@ namespace tp { } void draw(Canvas& canvas) override { - canvas.rect(this->mArea, this->getColor("Back")); + canvas.rect(this->mArea, mBGColor); if (mLogged) mChatting.draw(canvas); else mLogin.draw(canvas); } + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + + wm.addReference(this->mId, "Back", "Background"); + + mLogin.setupConfig(wm); + mChatting.setupConfig(wm); + } + + void updateConfigCache(const WidgetManager& wm) override { + mBGColor = wm.getColor(this->mId, "Back"); + + mLogin.updateConfigCache(wm); + mChatting.updateConfigCache(wm); + } + private: bool mLogged = false; LoginWidget mLogin; ChattingWidget mChatting; + + RGBA mBGColor; }; } \ No newline at end of file diff --git a/Widgets/examples/SimpleGUI.cpp b/Widgets/examples/SimpleGUI.cpp new file mode 100644 index 0000000..fd4ec5e --- /dev/null +++ b/Widgets/examples/SimpleGUI.cpp @@ -0,0 +1,50 @@ + +#include "ChatGUI.hpp" + +#include "GraphicApplication.hpp" + +using namespace tp; + +class SimpleGUI : public Application { +public: + SimpleGUI() { + mGui.setupConfig(mWidgetManager); + + mButton.setupConfig(mWidgetManager); + mSlider.setupConfig(mWidgetManager); + mLabel.setupConfig(mWidgetManager); + + mGui.mContents.append(&mButton); + mGui.mContents.append(&mSlider); + mGui.mContents.append(&mLabel); + } + + void processFrame(EventHandler* eventHandler) override { + + mGui.updateConfigCache(mWidgetManager); + + mSlider.updateConfigCache(mWidgetManager); + mLabel.updateConfigCache(mWidgetManager); + mButton.updateConfigCache(mWidgetManager); + + const auto rec = RectF({ 0, 0 }, mWindow->getSize()); + mGui.proc(*eventHandler, rec, rec); + } + + void drawFrame(Canvas* canvas) override { mGui.draw(*canvas); } + +private: + WidgetManager mWidgetManager; + ScrollableWindow mGui; + + ButtonWidget mButton; + LabelWidget mLabel; + SliderWidget mSlider; +}; + +int main() { + { + SimpleGUI gui; + gui.run(); + } +} diff --git a/Widgets/public/ButtonWidget.hpp b/Widgets/public/ButtonWidget.hpp index 8df41bc..4eb748c 100644 --- a/Widgets/public/ButtonWidget.hpp +++ b/Widgets/public/ButtonWidget.hpp @@ -9,22 +9,13 @@ namespace tp { public: ButtonWidget() { this->mArea = { 0, 0, 100, 100 }; - this->createConfig("Button"); - this->addColor("Pressed", "Action"); - this->addColor("Hovered", "Interaction"); - this->addColor("Default", "Accent"); - this->addValue("Rounding", "Rounding"); + this->mId = "Button"; } ButtonWidget(const std::string& label, const tp::RectF& aArea) { + this->mId = "Button"; this->mArea = aArea; this->mLabel.mLabel = label; - - this->createConfig("Button"); - this->addColor("Pressed", "Action"); - this->addColor("Hovered", "Interaction"); - this->addColor("Default", "Accent"); - this->addValue("Rounding", "Rounding"); } void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override { @@ -60,19 +51,45 @@ namespace tp { if (!this->mVisible) return; if (mIsPressed) { - canvas.rect(this->mArea, this->getColor("Pressed"), this->getValue("Rounding")); + canvas.rect(this->mArea, pressedColor, rounding); } else if (mIsHover) { - canvas.rect(this->mArea, this->getColor("Hovered"), this->getValue("Rounding")); + canvas.rect(this->mArea, hoveredColor, rounding); } else { - canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding")); + canvas.rect(this->mArea, accentColor, rounding); } mLabel.draw(canvas); } + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Pressed", "Action"); + wm.addReference(this->mId, "Hovered", "Interaction"); + wm.addReference(this->mId, "Default", "Accent"); + wm.addReference(this->mId, "Rounding", "Rounding"); + + mLabel.setupConfig(wm); + } + + void updateConfigCache(const WidgetManager& wm) override { + pressedColor = wm.getColor(this->mId, "Pressed"); + hoveredColor = wm.getColor(this->mId, "Hovered"); + accentColor = wm.getColor(this->mId, "Default"); + rounding = wm.getNumber(this->mId, "Rounding"); + + mLabel.updateConfigCache(wm); + } + public: LabelWidget mLabel; + bool mIsHover = false; bool mIsPressed = false; bool mIsReleased = false; + + RGBA pressedColor; + RGBA hoveredColor; + RGBA accentColor; + halnf rounding = 0; }; } \ No newline at end of file diff --git a/Widgets/public/LabelWidget.hpp b/Widgets/public/LabelWidget.hpp index 945436e..5fba4d1 100644 --- a/Widgets/public/LabelWidget.hpp +++ b/Widgets/public/LabelWidget.hpp @@ -6,14 +6,9 @@ namespace tp { template class LabelWidget : public Widget { public: - LabelWidget() { - this->createConfig("Label"); - this->addValue("Size", "FontSize"); - this->addValue("Padding", "Padding"); - this->addColor("Default", "Front"); - } + LabelWidget() { this->mId = "Label"; } - void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override { + void proc(const Events&, const tp::RectF& areaParent, const tp::RectF& aArea) override { this->mArea = aArea; this->mVisible = areaParent.isOverlap(aArea); if (!this->mVisible) return; @@ -21,18 +16,28 @@ namespace tp { void draw(Canvas& canvas) override { if (!this->mVisible) return; + canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::CC, padding, fontColor); + } - canvas.text( - mLabel.c_str(), - this->mArea, - this->getValue("Size"), - Canvas::CC, - this->getValue("Padding"), - this->getColor("Default") - ); + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Size", "FontSize"); + wm.addReference(this->mId, "Padding", "Padding"); + wm.addReference(this->mId, "Default", "Front"); + } + + void updateConfigCache(const WidgetManager& wm) override { + fontSize = wm.getNumber(this->mId, "Size"); + padding = wm.getNumber(this->mId, "Padding"); + fontColor = wm.getColor(this->mId, "Default"); } public: std::string mLabel = "Label"; + + halnf fontSize = 10; + halnf padding = 0; + RGBA fontColor = { 1, 1, 1, 1 }; }; } \ No newline at end of file diff --git a/Widgets/public/ScrollableWidget.hpp b/Widgets/public/ScrollableWidget.hpp index d955825..da93640 100644 --- a/Widgets/public/ScrollableWidget.hpp +++ b/Widgets/public/ScrollableWidget.hpp @@ -8,17 +8,7 @@ namespace tp { template class ScrollBarWidget : public Widget { public: - ScrollBarWidget() { - this->createConfig("ScrollBar"); - this->addColor("Default", "Base"); - this->addColor("Handle", "Accent"); - this->addColor("Hovered", "Interaction"); - this->addColor("Scrolling", "Action"); - this->addValue("Padding", "Padding"); - this->addValue("HandleSize", 20.f); - this->addValue("MinSize", 20.f); - this->addValue("Rounding", "Rounding"); - } + ScrollBarWidget() { this->mId = "ScrollBar"; } // takes whole area void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override { @@ -79,28 +69,22 @@ namespace tp { if (mSizeFraction > 1.f) return; // if (!areaParent.isOverlap(getHandle())) return; - tp::RGBA col = this->getColor("Handle"); + tp::RGBA col = mHandleColor; if (mIsScrolling) { - col = this->getColor("Scrolling"); + col = mScrollingColor; } else if (mHovered) { - col = this->getColor("Hovered"); + col = mHoveredColor; } - canvas.rect(area, this->getColor("Default"), this->getValue("Rounding")); + canvas.rect(area, mDefaultColor, mRounding); - canvas.rect(getHandleHandle(), col, this->getValue("Rounding")); + canvas.rect(getHandleHandle(), col, mRounding); } RectF getHandleHandle() const { - auto minSize = this->getValue("MinSize"); - if (mIsScrolling) { - minSize = this->getValue("MinSize") * 2; - } else if (mHovered) { - minSize = this->getValue("MinSize") * 2; - } auto area = getHandle(); - auto sliderSize = tp::clamp(area.w * mSizeFraction, minSize, area.w); + auto sliderSize = tp::clamp(area.w * mSizeFraction, mMinSize * 2, area.w); auto diffSize = sliderSize - area.w * mSizeFraction; return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize }; } @@ -109,14 +93,39 @@ namespace tp { if (mSizeFraction > 1.f) { return this->mArea; } - return { this->mArea.x, this->mArea.y, this->mArea.z - this->getValue("HandleSize"), this->mArea.w }; + return { this->mArea.x, this->mArea.y, this->mArea.z - mHandleSize, this->mArea.w }; } RectF getHandle() const { - return { this->mArea.x + this->mArea.z - this->getValue("HandleSize") + this->getValue("Padding"), - this->mArea.y + this->getValue("Padding"), - this->getValue("HandleSize") - this->getValue("Padding") * 2, - this->mArea.w - this->getValue("Padding") * 2 }; + return { this->mArea.x + this->mArea.z - mHandleSize + mPadding, + this->mArea.y + mPadding, + mHandleSize - mPadding * 2, + this->mArea.w - mPadding * 2 }; + } + + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + + wm.addReference(this->mId, "Default", "Base"); + wm.addReference(this->mId, "Handle", "Accent"); + wm.addReference(this->mId, "Hovered", "Interaction"); + wm.addReference(this->mId, "Scrolling", "Action"); + wm.addReference(this->mId, "Padding", "Padding"); + wm.addNumber(this->mId, "HandleSize", 20.f); + wm.addNumber(this->mId, "MinSize", 20.f); + wm.addReference(this->mId, "Rounding", "Rounding"); + } + + void updateConfigCache(const WidgetManager& wm) override { + mDefaultColor = wm.getColor(this->mId, "Default"); + mHandleColor = wm.getColor(this->mId, "Handle"); + mHoveredColor = wm.getColor(this->mId, "Hovered"); + mScrollingColor = wm.getColor(this->mId, "Scrolling"); + mPadding = wm.getNumber(this->mId, "Padding"); + mHandleSize = wm.getNumber(this->mId, "HandleSize"); + mMinSize = wm.getNumber(this->mId, "MinSize"); + mRounding = wm.getNumber(this->mId, "Rounding"); } public: @@ -126,16 +135,21 @@ namespace tp { halnf mSizeFraction = 1.f; halnf mPositionFraction = 0.f; bool mHovered = false; + + RGBA mDefaultColor; + RGBA mHandleColor; + RGBA mHoveredColor; + RGBA mScrollingColor; + halnf mPadding = 0; + halnf mHandleSize = 10; + halnf mMinSize = 10; + halnf mRounding = 10; }; template class ScrollableWindow : public Widget { public: - ScrollableWindow() { - this->createConfig("ScrollableWindow"); - this->addColor("Default", "Base"); - this->addValue("Padding", "Padding"); - } + ScrollableWindow() { this->mId = "ScrollableWindow"; } ~ScrollableWindow() = default; @@ -148,7 +162,7 @@ namespace tp { updateContents(); updateContentSize(); - const auto padding = this->getValue("Padding"); + const auto padding = mPadding; mScroller.mSizeFraction = this->mArea.w / mContentSize; mScroller.proc(events, this->mArea, this->mArea); @@ -180,16 +194,37 @@ namespace tp { canvas.popClamp(); } + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + + wm.addReference(this->mId, "Default", "Base"); + wm.addReference(this->mId, "Padding", "Padding"); + wm.addReference(this->mId, "Rounding", "Rounding"); + + mScroller.setupConfig(wm); + } + + void updateConfigCache(const WidgetManager& wm) override { + mDefaultColor = wm.getColor(this->mId, "Default"); + mPadding = wm.getNumber(this->mId, "Padding"); + + mScroller.updateConfigCache(wm); + + for (auto item : mContents) { + item->updateConfigCache(wm); + } + } + private: void updateContents() { if (mContents.size()) { - const auto padding = this->getValue("Padding"); - const halnf offset = mContents.first()->mArea.y + padding; + const halnf offset = mContents.first()->mArea.y + mPadding; halnf start = 0; for (auto widget : mContents) { widget->mArea.y = start; - start += widget->mArea.w + padding; + start += widget->mArea.w + mPadding; } for (auto widget : mContents) { @@ -201,17 +236,15 @@ namespace tp { void updateContentSize() { mContentSize = 0; if (mContents.size()) { - const auto padding = this->getValue("Padding"); mContentSize = mContents.last()->mArea.y - mContents.first()->mArea.y; mContentSize += mContents.last()->mArea.w; - mContentSize += 2 * padding; + mContentSize += 2 * mPadding; } } void setOffset(const halnf offset) { if (!mContents.size()) return; - const auto padding = this->getValue("Padding"); - auto newOffset = offset - mContents.first()->mArea.y + padding; + auto newOffset = offset - mContents.first()->mArea.y + mPadding; for (auto widget : mContents) { widget->mArea.y += newOffset; } @@ -219,7 +252,11 @@ namespace tp { public: halnf mContentSize = 0; + Buffer*> mContents; ScrollBarWidget mScroller; + + RGBA mDefaultColor; + halnf mPadding = 0; }; } \ No newline at end of file diff --git a/Widgets/public/SliderWidget.hpp b/Widgets/public/SliderWidget.hpp index 098d44e..70aa657 100644 --- a/Widgets/public/SliderWidget.hpp +++ b/Widgets/public/SliderWidget.hpp @@ -7,17 +7,7 @@ namespace tp { template class SliderWidget : public Widget { public: - SliderWidget() { - this->createConfig("SliderWidget"); - this->addColor("Default", "Base"); - this->addColor("Handle", "Accent"); - this->addColor("Hovered", "Interaction"); - this->addColor("Scrolling", "Action"); - this->addValue("Padding", "Padding"); - this->addValue("HandleSize", 20.f); - this->addValue("MinSize", 20.f); - this->addValue("Rounding", "Rounding"); - } + SliderWidget() { this->mId = "SliderWidget"; } void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override { this->mArea = aArea; @@ -31,7 +21,6 @@ namespace tp { } if (mIsSliding) { - const auto handleSize = this->getValue("HandleSize"); mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize); } @@ -40,26 +29,47 @@ namespace tp { void draw(Canvas& canvas) override { if (!this->mVisible) return; - canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding")); - canvas.rect(getHandle(), this->getColor("Handle"), this->getValue("Rounding")); + canvas.rect(this->mArea, defaultColor, rounding); + canvas.rect(getHandle(), handleColor, rounding); } RectF getHandle() const { - const auto handle = this->getValue("HandleSize"); - const auto halfHandle = handle / 2.f; - const auto left = this->mArea.x + (this->mArea.z - handle) * mFactor; - return { left, this->mArea.y, handle, this->mArea.w }; + const auto halfHandle = handleSize / 2.f; + const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor; + return { left, this->mArea.y, handleSize, this->mArea.w }; + } + + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Default", "Base"); + wm.addReference(this->mId, "Handle", "Accent"); + wm.addNumber(this->mId, "HandleSize", 20.f); + wm.addReference(this->mId, "Rounding", "Rounding"); + } + + void updateConfigCache(const WidgetManager& wm) override { + defaultColor = wm.getColor(this->mId, "Default"); + handleColor = wm.getColor(this->mId, "Handle"); + handleSize = wm.getNumber(this->mId, "HandleSize"); + rounding = wm.getNumber(this->mId, "Rounding"); } public: halnf mFactor = 0.f; bool mIsSliding = false; + + RGBA defaultColor; + RGBA handleColor; + halnf handleSize = 0; + halnf rounding = 0; }; template class NamedSliderWidget : public Widget { public: - NamedSliderWidget(const char* name = "Value") { + explicit NamedSliderWidget(const char* name = "Value") { + this->mId = "NamedSliderWidget"; mLabel.mLabel = name; this->mArea = { 0, 0, 100, 30 }; } @@ -89,6 +99,7 @@ namespace tp { mLabel.draw(canvas); } + public: public: SliderWidget mSlider; LabelWidget mLabel; diff --git a/Widgets/public/SplitViewWidget.hpp b/Widgets/public/SplitViewWidget.hpp index 2ee1ad8..6731efa 100644 --- a/Widgets/public/SplitViewWidget.hpp +++ b/Widgets/public/SplitViewWidget.hpp @@ -6,14 +6,7 @@ namespace tp { template class SplitView : public Widget { public: - SplitView() { - this->createConfig("SplitView"); - this->addColor("Handle", "Accent"); - this->addColor("Hovered", "Interaction"); - this->addColor("Resizing", "Action"); - this->addValue("Min", 200.f); - this->addValue("HandleSize", 7.f); - } + SplitView() { this->mId = "SplitView"; } void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override { this->mArea = aArea; @@ -38,9 +31,9 @@ namespace tp { mFactor += diff / this->mArea.z; } - mFactor = tp::clamp(mFactor, this->getValue("Min") / this->mArea.z, 1 - this->getValue("Min") / this->mArea.z); + mFactor = tp::clamp(mFactor, mMinSize / this->mArea.z, 1 - mMinSize / this->mArea.z); - if (this->getValue("Min") * 2.f > this->mArea.z) { + if (mMinSize * 2.f > this->mArea.z) { mFactor = 0.5f; } } @@ -49,34 +42,52 @@ namespace tp { void draw(Canvas& canvas) override { if (!this->mVisible) return; - if (mResizeInProcess) canvas.rect(getHandle(), this->getColor("Resizing")); - else if (mIsHover) canvas.rect(getHandle(), this->getColor("Hovered")); - else canvas.rect(getHandle(), this->getColor("Handle")); + if (mResizeInProcess) canvas.rect(getHandle(), mResizingColor); + else if (mIsHover) canvas.rect(getHandle(), mHoveredColor); + else canvas.rect(getHandle(), mHandleColor); } RectF getFirst() const { - return { - this->mArea.x, this->mArea.y, mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f, this->mArea.w - }; + return { this->mArea.x, this->mArea.y, mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.w }; } RectF getSecond() const { - return { this->mArea.x + mFactor * this->mArea.z + this->getValue("HandleSize") / 2.f, + return { this->mArea.x + mFactor * this->mArea.z + mHandleSize / 2.f, this->mArea.y, - (1.f - mFactor) * this->mArea.z - this->getValue("HandleSize") / 2.f, + (1.f - mFactor) * this->mArea.z - mHandleSize / 2.f, this->mArea.w }; } RectF getHandle() const { - return { this->mArea.x + mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f, - this->mArea.y, - this->getValue("HandleSize"), - this->mArea.w }; + return { this->mArea.x + mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.y, mHandleSize, this->mArea.w }; + } + + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Handle", "Accent"); + wm.addReference(this->mId, "Hovered", "Interaction"); + wm.addReference(this->mId, "Resizing", "Action"); + wm.addNumber(this->mId, "Min", 200.f); + wm.addNumber(this->mId, "HandleSize", 7.f); + } + + void updateConfigCache(const WidgetManager& wm) override { + mHandleColor = wm.getColor(this->mId, "Handle"); + mHoveredColor = wm.getColor(this->mId, "Hovered"); + mResizingColor = wm.getColor(this->mId, "Resizing"); + mMinSize = wm.getNumber(this->mId, "Min"); + mHandleSize = wm.getNumber(this->mId, "HandleSize"); } public: halnf mFactor = 0.7f; bool mResizeInProcess = false; bool mIsHover = false; + + RGBA mHandleColor; + RGBA mHoveredColor; + RGBA mResizingColor; + halnf mMinSize = 0; + halnf mHandleSize = 0; }; } \ No newline at end of file diff --git a/Widgets/public/TextInputWidget.hpp b/Widgets/public/TextInputWidget.hpp index 11089cb..2dfd40b 100644 --- a/Widgets/public/TextInputWidget.hpp +++ b/Widgets/public/TextInputWidget.hpp @@ -9,14 +9,7 @@ namespace tp { template class TextInputWidget : public Widget { public: - TextInputWidget() { - this->createConfig("TextInput"); - this->addColor("Accent", "Accent"); - this->addColor("Base", "Base"); - this->addValue("Rounding", "Rounding"); - this->addColor("Hovered", "Interaction"); - this->addValue("Padding", "Padding"); - } + TextInputWidget() { this->mId = "TextInput"; } void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override { this->mArea = aArea; @@ -29,8 +22,8 @@ namespace tp { nChanged = false; - const auto col = this->getColor("Accent"); - const auto colSel = this->getColor("Hovered"); + const auto col = mAccentColor; + const auto colSel = mHoveredColor; ImGui::GetStyle().Colors[ImGuiCol_FrameBg] = { col.r, col.g, col.b, col.a }; ImGui::GetStyle().Colors[ImGuiCol_TextSelectedBg] = { colSel.r, colSel.g, colSel.b, colSel.a }; @@ -38,8 +31,8 @@ namespace tp { ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y }); ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w }); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 }); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, this->getValue("Rounding") * 1.5f); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { this->getValue("Padding"), this->getValue("Padding") }); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding }); // ImGui::PushID((int) alni(this)); ImGui::Begin( @@ -65,11 +58,36 @@ namespace tp { ImGui::PopStyleVar(3); } + public: + void setupConfig(WidgetManager& wm) { + if (!wm.createWidgetConfig(this->mId)) return; + wm.addReference(this->mId, "Accent", "Accent"); + wm.addReference(this->mId, "Base", "Base"); + wm.addReference(this->mId, "Rounding", "Rounding"); + wm.addReference(this->mId, "Hovered", "Accent"); + wm.addReference(this->mId, "Padding", "Padding"); + } + + void updateConfigCache(const WidgetManager& wm) override { + mAccentColor = wm.getColor(this->mId, "Accent"); + mBaseColor = wm.getColor(this->mId, "Base"); + mHoveredColor = wm.getColor(this->mId, "Hovered"); + mRounding = wm.getNumber(this->mId, "Rounding"); + mPadding = wm.getNumber(this->mId, "Padding"); + } + + public: enum { mMaxBufferSize = 512 }; char mBuff[mMaxBufferSize] = ""; bool nChanged = false; std::string mValue; std::string mId = "id"; bool mMultiline = false; + + RGBA mAccentColor; + RGBA mHoveredColor; + RGBA mBaseColor; + halnf mRounding = 0; + halnf mPadding = 0; }; } \ No newline at end of file diff --git a/Widgets/public/WidgetBase.hpp b/Widgets/public/WidgetBase.hpp index b9bf46c..8eae05f 100644 --- a/Widgets/public/WidgetBase.hpp +++ b/Widgets/public/WidgetBase.hpp @@ -1,56 +1,14 @@ -; #pragma once -#include "WidgetConfig.hpp" +#include "WidgetManager.hpp" namespace tp { template class Widget { public: - using WidgetConfig = WidgetConfig; - using WidgetNode = WidgetConfig::Node; - using GlobalGUIConfig = GlobalGUIConfig; - Widget() { this->mArea = { 0, 0, 100, 100 }; } - virtual void populateConfig() {} - - [[nodiscard]] const RGBA& getColor(const std::string& name) const { - const auto& node = cfg->values.get(name); - if (node.type == WidgetNode::REF) { - return mGlobalCfg.configs.get(node.refGroup).values.get(node.refName).color; - } - return cfg->values.get(name).color; - } - - [[nodiscard]] halnf getValue(const std::string& name) const { - const auto& node = cfg->values.get(name); - if (node.type == WidgetNode::REF) { - return mGlobalCfg.configs.get(node.refGroup).values.get(node.refName).value; - } - return cfg->values.get(name).value; - } - - void addColor(const std::string& name, const RGBA& val) { cfg->values.put(name, WidgetNode(val)); } - void addValue(const std::string& name, halnf val) { cfg->values.put(name, WidgetNode(val)); } - - void addColor(const std::string& name, const std::string& presetName) { - cfg->values.put(name, WidgetNode(presetName)); - } - void addValue(const std::string& name, const std::string& presetName) { - cfg->values.put(name, WidgetNode(presetName)); - } - - bool createConfig(const std::string& name) { - auto idx = mGlobalCfg.configs.presents(name); - if (idx) return false; - mGlobalCfg.configs.put(name, {}); - cfg = &mGlobalCfg.configs.get(name); - populateConfig(); - return true; - } - virtual void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) { mVisible = areaParent.isOverlap(aArea); if (!mVisible) { @@ -66,19 +24,11 @@ namespace tp { } } - void addOperator(const std::string& name, WidgetConfig::WidgetCallback callback) { - cfg->mOperators.put(name, callback); - } - - Buffer& getShortcuts(const std::string& name) { return cfg->mShortcuts[name]; } + virtual void updateConfigCache(const WidgetManager& wm) = 0; public: - static GlobalGUIConfig mGlobalCfg; - WidgetConfig* cfg = nullptr; + std::string mId; RectF mArea; bool mVisible = false; }; - - template - GlobalGUIConfig Widget::mGlobalCfg; } \ No newline at end of file diff --git a/Widgets/public/WidgetConfig.hpp b/Widgets/public/WidgetConfig.hpp deleted file mode 100644 index cbf37df..0000000 --- a/Widgets/public/WidgetConfig.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include "Animations.hpp" -#include "Map.hpp" -#include "Rect.hpp" - -#include "InputCodes.hpp" -#include "Buffer.hpp" - -namespace tp { - - struct WidgetShortcut { - struct Condition { - std::string name; - std::string state; - }; - - WidgetShortcut() = default; - WidgetShortcut(const InitialierList&) {} - }; - - template - struct WidgetConfig { - - struct WidgetCallback { - using CallbackType = void (*)(void* self, const Events&); - void* self; - CallbackType callback; - }; - - struct Node { - enum Type { NONE, VAL, COL, REF }; - - halnf value = 0.f; - RGBA color = {}; - - Type type = NONE; - - std::string refGroup; - std::string refName; - - Node() = default; - - explicit Node(halnf val) { - type = VAL; - value = val; - } - - explicit Node(const RGBA& val) { - type = COL; - color = val; - } - - explicit Node(const std::string& val) { - refGroup = "Presets"; - refName = val; - type = REF; - } - }; - - Map values; - Map mOperators; - Map> mShortcuts; - }; - - template - struct GlobalGUIConfig { - using WidgetConfig = WidgetConfig; - using WidgetNode = WidgetConfig::Node; - - GlobalGUIConfig() { - configs.put("Presets", {}); - auto& presets = configs.get("Presets"); - - presets.values.put("FontSize", WidgetNode(15.f)); - presets.values.put("FontSizeDim", WidgetNode(12.f)); - presets.values.put("Rounding", WidgetNode(5.f)); - presets.values.put("Padding", WidgetNode(5.f)); - presets.values.put("HandleSize", WidgetNode(5.f)); - - presets.values.put("Background", WidgetNode(RGBA{ 0.03f, 0.03f, 0.03f, 1.f })); - presets.values.put("Base", WidgetNode(RGBA{ 0.07f, 0.07f, 0.07f, 1.f })); - presets.values.put("Accent", WidgetNode(RGBA{ 0.13f, 0.13f, 0.13f, 1.f })); - presets.values.put("Interaction", WidgetNode(RGBA{ 0.33f, 0.33f, 0.3f, 1.f })); - presets.values.put("Action", WidgetNode(RGBA{ 0.44f, 0.44f, 0.4f, 1.f })); - presets.values.put("Front", WidgetNode(RGBA{ 1.f, 1.f, 1.f, 1.f })); - presets.values.put("FrontDim", WidgetNode(RGBA{ 0.7f, 0.7f, 0.7f, 1.f })); - } - - ~GlobalGUIConfig() { configs.removeAll(); } - - void processShortcuts(const Events& events) { - // - } - - Map configs; - }; -} \ No newline at end of file diff --git a/Widgets/public/WidgetManager.hpp b/Widgets/public/WidgetManager.hpp new file mode 100644 index 0000000..e254a7d --- /dev/null +++ b/Widgets/public/WidgetManager.hpp @@ -0,0 +1,131 @@ +#pragma once + +#include "Animations.hpp" +#include "Map.hpp" +#include "Rect.hpp" + +#include "InputCodes.hpp" +#include "Buffer.hpp" + +namespace tp { + + struct WidgetConfig { + + struct WidgetShortcut { + struct Condition { + std::string name; + std::string state; + }; + + std::string callbackName; + + WidgetShortcut() = default; + WidgetShortcut(const InitialierList&) {} + }; + + struct WidgetParameter { + enum Type { NONE, VAL, COL, REF }; + + halnf value = 0.f; + RGBA color = {}; + + std::string refName; + std::string refWidgetId; + + Type type = NONE; + + WidgetParameter() = default; + + explicit WidgetParameter(halnf val) { + type = VAL; + value = val; + } + + explicit WidgetParameter(const RGBA& val) { + type = COL; + color = val; + } + + explicit WidgetParameter(const std::string& widgetId, const std::string& val) { + type = REF; + refName = val; + refWidgetId = widgetId; + } + }; + + Map mParameters; + Buffer mShortcuts; + }; + + class WidgetManager { + public: + WidgetManager() { + createWidgetConfig("Default"); + + addNumber("Default", "FontSize", 15.f); + addNumber("Default", "FontSizeDim", 12.f); + addNumber("Default", "Rounding", 5.f); + addNumber("Default", "Padding", 5.f); + addNumber("Default", "HandleSize", 5.f); + + addColor("Default", "Background", RGBA{ 0.03f, 0.03f, 0.03f, 1.f }); + addColor("Default", "Base", RGBA{ 0.07f, 0.07f, 0.07f, 1.f }); + addColor("Default", "Accent", RGBA{ 0.13f, 0.13f, 0.13f, 1.f }); + addColor("Default", "Interaction", RGBA{ 0.33f, 0.33f, 0.3f, 1.f }); + addColor("Default", "Action", RGBA{ 0.44f, 0.44f, 0.4f, 1.f }); + addColor("Default", "Front", RGBA{ 1.f, 1.f, 1.f, 1.f }); + addColor("Default", "FrontDim", RGBA{ 0.7f, 0.7f, 0.7f, 1.f }); + } + + ~WidgetManager() { mConfigurations.removeAll(); } + + bool createWidgetConfig(const std::string& widgetId) { + auto idx = mConfigurations.presents(widgetId); + if (idx) return false; + mConfigurations.put(widgetId, {}); + return true; + } + + [[nodiscard]] const RGBA& getColor(const std::string& widgetId, const std::string& name) const { + const WidgetConfig& config = mConfigurations.get(widgetId); + const WidgetConfig::WidgetParameter& parameter = config.mParameters.get(name); + + if (parameter.type == WidgetConfig::WidgetParameter::REF) { + return mConfigurations.get(parameter.refWidgetId).mParameters.get(parameter.refName).color; + } else { + return parameter.color; + } + } + + [[nodiscard]] halnf getNumber(const std::string& widgetId, const std::string& name) const { + const WidgetConfig& config = mConfigurations.get(widgetId); + const WidgetConfig::WidgetParameter& parameter = config.mParameters.get(name); + + if (parameter.type == WidgetConfig::WidgetParameter::REF) { + return mConfigurations.get(parameter.refWidgetId).mParameters.get(parameter.refName).value; + } else { + return parameter.value; + } + } + + void addColor(const std::string& widgetId, const std::string& name, const RGBA& val) { + WidgetConfig& config = mConfigurations.get(widgetId); + config.mParameters.put(name, WidgetConfig::WidgetParameter(val)); + } + + void addNumber(const std::string& widgetId, const std::string& name, halnf val) { + WidgetConfig& config = mConfigurations.get(widgetId); + config.mParameters.put(name, WidgetConfig::WidgetParameter(val)); + } + + void addReference(const std::string& widgetId, const std::string& refName, const std::string& name) { + WidgetConfig& config = mConfigurations.get(widgetId); + config.mParameters.put(refName, WidgetConfig::WidgetParameter("Default", name)); + } + + private: + Map mConfigurations; + RGBA mErrorColor = { 0, 0, 0, 1 }; + halnf mErrorNumber = 0; + }; +} \ No newline at end of file