diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt index 9fbaefe..268e92f 100644 --- a/frame/CMakeLists.txt +++ b/frame/CMakeLists.txt @@ -39,16 +39,16 @@ set(src src/widgets/Widget.hpp src/widgets/Widget.cpp + src/widgets/ContainerWidget.hpp + src/widgets/ContainerWidget.cpp src/widgets/WidgetRegistry.hpp src/widgets/WidgetRegistry.cpp src/widgets/clock/Digital.hpp src/widgets/clock/Digital.cpp src/widgets/clock/Analog.hpp src/widgets/clock/Analog.cpp - - - - + src/widgets/clock/Date.hpp + src/widgets/clock/Date.cpp ) diff --git a/frame/src/ScreenManager.cpp b/frame/src/ScreenManager.cpp index 833eabc..7b8eef3 100644 --- a/frame/src/ScreenManager.cpp +++ b/frame/src/ScreenManager.cpp @@ -32,11 +32,11 @@ namespace frame if(mRoot) { mRenderTarget.Clear(); + + mRoot->setSize(mDisplay->getSize()); mRoot->Render(mRenderTarget); - if(mDisplay) - { - mDisplay->Display(mRenderTarget.getImage()); - } + + mDisplay->Display(mRenderTarget.getImage()); } } diff --git a/frame/src/main.cpp b/frame/src/main.cpp index e11dfc6..838e278 100644 --- a/frame/src/main.cpp +++ b/frame/src/main.cpp @@ -11,6 +11,7 @@ using namespace std::chrono_literals; #include "font/FontRegistry.hpp" //#include "render/RenderTarget.hpp" //#include "widgets/clock/Analog.hpp" +#include "widgets/ContainerWidget.hpp" #include "widgets/WidgetRegistry.hpp" int main() @@ -30,7 +31,14 @@ int main() auto const& widgets = frame::Service::get(); - screen.setRoot(widgets->Create("AnalogClock")); + std::shared_ptr con = + std::static_pointer_cast( + widgets->Create("AnalogClock")); + + con->setSlot(0, widgets->Create("DigitalClock")); + con->setSlot(1, widgets->Create("Date")); + + screen.setRoot(con); screen.MainLoop(); } diff --git a/frame/src/widgets/ContainerWidget.cpp b/frame/src/widgets/ContainerWidget.cpp new file mode 100644 index 0000000..cb20f2d --- /dev/null +++ b/frame/src/widgets/ContainerWidget.cpp @@ -0,0 +1,34 @@ +#include "ContainerWidget.hpp" + +namespace frame::widgets +{ + ContainerWidget::ContainerWidget(size_t slots) + { + widgets.resize(slots); + maxSlots = slots; + } + + Widget::shared_ptr ContainerWidget::getSlot(size_t slot) const + { + if(slot >= maxSlots) + return nullptr; + return widgets[slot]; + } + + void ContainerWidget::setSlot(size_t slot, Widget::shared_ptr ptr) + { + widgets[slot] = ptr; + } + + void ContainerWidget::UpdateWidgets() + { + for(auto& el : widgets) + { + if(el) + { + el->Update(); + } + } + } + +} // namespace frame::widgets \ No newline at end of file diff --git a/frame/src/widgets/ContainerWidget.hpp b/frame/src/widgets/ContainerWidget.hpp new file mode 100644 index 0000000..f30e763 --- /dev/null +++ b/frame/src/widgets/ContainerWidget.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "Widget.hpp" + +#include + +namespace frame::widgets +{ + + class ContainerWidget : public Widget + { + std::vector widgets; + size_t maxSlots = 0; + + public: + ContainerWidget(size_t slots); + + Widget::shared_ptr getSlot(size_t slot) const; + void setSlot(size_t slot, Widget::shared_ptr); + + void UpdateWidgets(); + }; + +} // namespace frame::widgets diff --git a/frame/src/widgets/clock/Analog.cpp b/frame/src/widgets/clock/Analog.cpp index 6462245..45e0086 100644 --- a/frame/src/widgets/clock/Analog.cpp +++ b/frame/src/widgets/clock/Analog.cpp @@ -20,6 +20,11 @@ namespace frame::widgets return std::make_shared(); } + AnalogClock::AnalogClock() + : ContainerWidget(2) + { + } + void AnalogClock::Update() { auto const now = std::chrono::system_clock::now(); @@ -30,6 +35,8 @@ namespace frame::widgets setDirty(); last_time = min; } + + UpdateWidgets(); } void AnalogClock::Render(render::RenderTarget& rt) @@ -97,9 +104,54 @@ namespace frame::widgets setClear(); + // == Widgets == + + auto widget_center_1 = center; + widget_center_1.y -= radius / 2; + + auto widget_center_2 = center; + widget_center_2.y += radius / 2; + + auto const widget_height_h = radius / 4; + auto const widget_width_h = radius / 2; + + Rect widget_box_1{widget_center_1.y - widget_height_h, + widget_center_1.x - widget_width_h, + widget_width_h * 2, + widget_height_h * 2}; + + Rect widget_box_2{widget_center_2.y - widget_height_h, + widget_center_2.x - widget_width_h, + widget_width_h * 2, + widget_height_h * 2}; + + // Top + + rt.setInvert(true); + + auto top = getSlot(0); + if(top) + { + top->setSize({widget_box_1.width, widget_box_1.height}); + rt.pushViewport(widget_box_1); + top->Render(rt); + rt.popViewport(); + } + + auto bottom = getSlot(1); + if(bottom) + { + bottom->setSize({widget_box_2.width, widget_box_2.height}); + rt.pushViewport(widget_box_2); + bottom->Render(rt); + rt.popViewport(); + } + + rt.setInvert(false); + // Text - auto font = font::GetFont("Fira Code"); + /*auto font = font::GetFont("Fira Code"); if(!font) return; @@ -126,7 +178,7 @@ namespace frame::widgets font_size, AlignHorizontal::CENTER, AlignVertical::CENTER); - rt.setInvert(false); + rt.setInvert(false);*/ } } // namespace frame::widgets \ No newline at end of file diff --git a/frame/src/widgets/clock/Analog.hpp b/frame/src/widgets/clock/Analog.hpp index e8af0b3..775dd18 100644 --- a/frame/src/widgets/clock/Analog.hpp +++ b/frame/src/widgets/clock/Analog.hpp @@ -1,13 +1,13 @@ #pragma once -#include "../Widget.hpp" +#include "../ContainerWidget.hpp" #include namespace frame::widgets { - class AnalogClock : public Widget + class AnalogClock : public ContainerWidget { using Time = std::chrono::time_point; @@ -16,6 +16,8 @@ namespace frame::widgets public: static Widget::shared_ptr Create(); + AnalogClock(); + void Update() override; void Render(render::RenderTarget& rt) override; }; diff --git a/frame/src/widgets/clock/Date.cpp b/frame/src/widgets/clock/Date.cpp new file mode 100644 index 0000000..693c645 --- /dev/null +++ b/frame/src/widgets/clock/Date.cpp @@ -0,0 +1,54 @@ +#include "Date.hpp" + +REGISTER_WIDGET(frame::widgets::Date, "Date"); + +#include "../../font/FontRegistry.hpp" + +#include +#include +#include + +namespace frame::widgets +{ + + Widget::shared_ptr Date::Create() + { + return std::make_shared(); + } + + void Date::Update() + { + auto const now = std::chrono::system_clock::now(); + auto const min = std::chrono::floor(now); + + if(last_time != min) + { + setDirty(); + last_time = min; + } + } + + void Date::Render(render::RenderTarget& rt) + { + std::time_t t = std::chrono::system_clock::to_time_t(last_time); + + auto const& size = getSize(); + Rect draw{0, 0, size.x, size.y}; + + auto text = fmt::format("{:%d.%m.%Y}", fmt::localtime(t)); + + auto font = font::GetFont("Fira Code"); + + auto font_size = font->getOptimalSize(text, draw); + + rt.DrawText(draw, + text, + *font, + font_size, + AlignHorizontal::CENTER, + AlignVertical::CENTER); + + setClear(); + } + +} // namespace frame::widgets \ No newline at end of file diff --git a/frame/src/widgets/clock/Date.hpp b/frame/src/widgets/clock/Date.hpp new file mode 100644 index 0000000..83a990e --- /dev/null +++ b/frame/src/widgets/clock/Date.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "../Widget.hpp" +#include "../WidgetRegistry.hpp" + +#include + +namespace frame::widgets +{ + class Date : public Widget + { + using Time = std::chrono::time_point; + + Time last_time; + + public: + static Widget::shared_ptr Create(); + + void Update() override; + void Render(render::RenderTarget& rt) override; + }; +} // namespace frame::widgets \ No newline at end of file diff --git a/frame/src/widgets/clock/Digital.cpp b/frame/src/widgets/clock/Digital.cpp index e69de29..c88ec48 100644 --- a/frame/src/widgets/clock/Digital.cpp +++ b/frame/src/widgets/clock/Digital.cpp @@ -0,0 +1,56 @@ +#include "Digital.hpp" + +REGISTER_WIDGET(frame::widgets::DigitalClock, "DigitalClock"); + +#include "../../font/FontRegistry.hpp" + +#include +#include +#include + +namespace frame::widgets +{ + + Widget::shared_ptr DigitalClock::Create() + { + return std::make_shared(); + } + + void DigitalClock::Update() + { + auto const now = std::chrono::system_clock::now(); + auto const min = std::chrono::floor(now); + + if(last_time != min) + { + setDirty(); + last_time = min; + } + } + + void DigitalClock::Render(render::RenderTarget& rt) + { + std::time_t t = std::chrono::system_clock::to_time_t(last_time); + auto c_time = std::localtime(&t); + + auto const& size = getSize(); + Rect draw{0, 0, size.x, size.y}; + + auto text = + fmt::format("{:0^2}:{:0^2}", c_time->tm_hour, c_time->tm_min); + + auto font = font::GetFont("Fira Code"); + + auto font_size = font->getOptimalSize(text, draw); + + rt.DrawText(draw, + text, + *font, + font_size, + AlignHorizontal::CENTER, + AlignVertical::CENTER); + + setClear(); + } + +} // namespace frame::widgets \ No newline at end of file diff --git a/frame/src/widgets/clock/Digital.hpp b/frame/src/widgets/clock/Digital.hpp index e69de29..90710b4 100644 --- a/frame/src/widgets/clock/Digital.hpp +++ b/frame/src/widgets/clock/Digital.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "../Widget.hpp" +#include "../WidgetRegistry.hpp" + +namespace frame::widgets +{ + + class DigitalClock : public Widget + { + using Time = std::chrono::time_point; + + Time last_time; + + public: + static Widget::shared_ptr Create(); + + void Update() override; + void Render(render::RenderTarget& rt) override; + }; + +} // namespace frame::widgets \ No newline at end of file