diff --git a/frame/src/Config.cpp b/frame/src/Config.cpp index 6c52bdc..fef1908 100644 --- a/frame/src/Config.cpp +++ b/frame/src/Config.cpp @@ -7,6 +7,14 @@ namespace fs = std::filesystem; #define PROPERTY(str, member) str.member = j.value(#member, str.member) +#define PROPERTY_OPT(str, member, type) \ + str.member = \ + j.contains(#member) ? j[#member].get() : std::optional{}; + +#define OBJ(str, mem) \ + { \ +# mem, str.mem \ + } Config Config::Load() { @@ -14,9 +22,20 @@ Config Config::Load() if(fs::is_regular_file(config_path)) { - std::fstream file(config_path.string(), std::ios::in); + try + { + std::fstream file(config_path.string(), std::ios::in); - return json::parse(file); + return json::parse(file); + } + catch(std::exception const& e) + { + fmt::print("Error: {}\n", e.what()); + + // TODO: Create Error Display Widget + + return {}; + } } fmt::print("[INFO] Creating config file\n"); @@ -30,22 +49,41 @@ Config Config::Load() // == to json == void to_json(json& j, Config const& c) { - j = {{"font", c.font}}; + j = {OBJ(c, font), OBJ(c, root)}; } void to_json(json& j, FontConfig const& fc) { - j = {{"base_path", fc.base_path}, {"fonts", fc.fonts}}; + j = {OBJ(fc, base_path), OBJ(fc, fonts)}; +} + +void to_json(json& j, WidgetConfig const& w) +{ + j = {OBJ(w, name), OBJ(w, parameters), OBJ(w, widgets)}; + + if(w.slot) + { + j["slot"] = w.slot.value(); + } } // == from json == void from_json(json const& j, Config& c) { PROPERTY(c, font); + PROPERTY(c, root); } void from_json(json const& j, FontConfig& fc) { PROPERTY(fc, base_path); PROPERTY(fc, fonts); -} \ No newline at end of file +} + +void from_json(json const& j, WidgetConfig& w) +{ + PROPERTY(w, name); + PROPERTY(w, parameters); + PROPERTY(w, widgets); + PROPERTY_OPT(w, slot, int); +} diff --git a/frame/src/Config.hpp b/frame/src/Config.hpp index 2c03616..390a5d3 100644 --- a/frame/src/Config.hpp +++ b/frame/src/Config.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include @@ -12,15 +13,26 @@ struct FontConfig {"Fira Code", "FiraCode.json"}}; }; +struct WidgetConfig +{ + std::string name = "DigitalClock"; + std::unordered_map parameters = {}; + std::vector widgets = {}; + std::optional slot = {}; +}; + struct Config { FontConfig font{}; + WidgetConfig root{}; static Config Load(); }; void to_json(json& j, Config const& c); void to_json(json& j, FontConfig const& fc); +void to_json(json& j, WidgetConfig const& w); void from_json(json const& j, Config& c); -void from_json(json const& j, FontConfig& fc); \ No newline at end of file +void from_json(json const& j, FontConfig& fc); +void from_json(json const& j, WidgetConfig& w); \ No newline at end of file diff --git a/frame/src/main.cpp b/frame/src/main.cpp index 5b5d431..96f118d 100644 --- a/frame/src/main.cpp +++ b/frame/src/main.cpp @@ -38,14 +38,15 @@ int main() auto const& widgets = frame::Service::get(); - std::shared_ptr con = - std::static_pointer_cast( - widgets->Create("AnalogClock")); + // std::shared_ptr con = + // std::static_pointer_cast( + // widgets->Create("AnalogClock")); - con->setSlot(0, widgets->Create("DigitalClock")); + // con->setSlot(0, widgets->Create("DigitalClock")); - con->setSlot(1, widgets->Create("Date")); + // con->setSlot(1, widgets->Create("Date")); + auto con = frame::widgets::LocateRegistry().BuildFromConfig(config.root); screen.setRoot(con); screen.MainLoop(); diff --git a/frame/src/widgets/WidgetRegistry.cpp b/frame/src/widgets/WidgetRegistry.cpp index 561f581..61e087f 100644 --- a/frame/src/widgets/WidgetRegistry.cpp +++ b/frame/src/widgets/WidgetRegistry.cpp @@ -1,5 +1,7 @@ #include "WidgetRegistry.hpp" +#include "ContainerWidget.hpp" + namespace frame::widgets { @@ -19,4 +21,23 @@ namespace frame::widgets return it->second(); } + Widget::shared_ptr WidgetRegistry::BuildFromConfig(WidgetConfig const& w) + { + fmt::print("INFO: Creating widget {} \n", w.name); + auto widget = Create(w.name); + + auto container = std::dynamic_pointer_cast(widget); + if(container) + { + int counter = 0; + for(auto const& el : w.widgets) + { + int slot = el.slot ? el.slot.value() : counter; + + container->setSlot(slot, BuildFromConfig(el)); + } + } + return widget; + } + } // namespace frame::widgets \ No newline at end of file diff --git a/frame/src/widgets/WidgetRegistry.hpp b/frame/src/widgets/WidgetRegistry.hpp index 315d490..b153038 100644 --- a/frame/src/widgets/WidgetRegistry.hpp +++ b/frame/src/widgets/WidgetRegistry.hpp @@ -1,4 +1,5 @@ #pragma once +#include "../Config.hpp" #include "../ServiceLocator.hpp" #include "Widget.hpp" @@ -14,7 +15,6 @@ namespace frame::widgets { - class WidgetRegistry : public IService { @@ -29,8 +29,15 @@ namespace frame::widgets bool Register(std::string_view name); Widget::shared_ptr Create(std::string_view name) const; + + Widget::shared_ptr BuildFromConfig(WidgetConfig const& w); }; + inline WidgetRegistry& LocateRegistry() + { + return *Service::get(); + } + template bool WidgetRegistry::Register(std::string_view name) {