From 97bd1178684ed9da607dde251b27497df82d040e Mon Sep 17 00:00:00 2001 From: Dawid Wojtas Date: Mon, 3 Oct 2022 15:28:35 +0200 Subject: [PATCH] [BH-1577][BH-1578] New Power Nap layout Add circular progress bar to power nap. Ringing bell image at the end of the power nap. --- art/bell/big_bell_ringing_W_G.png | Bin 0 -> 2021 bytes harmony_changelog.md | 11 ++ products/BellHybrid/CMakeLists.txt | 4 +- .../data/PowerNapStyle.hpp | 44 ++++- .../presenter/PowerNapProgressPresenter.cpp | 20 +- .../presenter/PowerNapProgressPresenter.hpp | 25 ++- .../windows/PowerNapProgressWindow.cpp | 171 ++++++++++-------- .../windows/PowerNapProgressWindow.hpp | 38 ++-- products/BellHybrid/assets/assets_common.json | 1 + 9 files changed, 205 insertions(+), 109 deletions(-) create mode 100644 art/bell/big_bell_ringing_W_G.png diff --git a/art/bell/big_bell_ringing_W_G.png b/art/bell/big_bell_ringing_W_G.png new file mode 100644 index 0000000000000000000000000000000000000000..cbd7f61769e8c744fc55c3f3879636c448d0bed1 GIT binary patch literal 2021 zcmZ{leK-?(8^?b+G*he7aE4PErcA1B&D*lhFl@YP2`IEQ|B!fF9YA}Bzwk0s5q2He&Pj!z*`IzxpYUo3Vvz=pUcB1a+Y3~ZP?Q1bt< z8o_fWJ1N&1tm7#!X6gZ`o#;gP&sp4>hO{;(onPJ<#hz<)j$+P)6g~c6@OeITRXXEh zY%4s`C{=xxtsd3#$L=VT+@ION^S2PS?W=ot#?BaO0#Qv64YdVCFW%HOT@pSwNKFTv zq3j;@=w95}SiQL<^hfR9E=7RsR`|h@0Nr1-qx*;huD6T6IZSn9KRiZ@m)}yiP_=KT zT2p%4*Awd&=M%eH%+0lrciTM7ak?0HJkbpO>sX`h7oDX_dNX?Wfu|IRYsd4I2Qzmx zMzg;iJ-?V~bU~YgYRStuOUOuS=RvaY$^EY=ju&YGz0#w`+ zM&z%~+LPU910uyXMQK{&@r`=fL?F8?*f*v>BWa#Bx3L`d`xGfcxZ*?TE`!0rF-bc} zo4pJdDr$D7g};snJv_LiX618AaVaES;x|X+j@LMDzrTB{wWOIkdKe#nIdTs+838yI z)M!2v%U-Thv6cj*Yh41jgZU&@5!G2_MNz1Bs=jyI-QJ-*NPSV+43PdDF_h?1b$je9 zpA8kXc3JUoUbI|TN+LDS=j4ZxRz=`hm8zCk4^iFly62J8?=irAm~qWEQ$IQvdwTNy z?F($dMFC%P4v8*(p!ewLS}QerX4g#ua+96J#-mTaX^9MXOY(>E%%ir^dvTgHDCRE1y!%CvgiE zJcVub8seapTM0hdFtG&nQiC0MQUlpNdTd+PsNzTmewo{b@D9K#Z9965k{}~ZoBIZ> zl`>$~<^IwL2h|FwKgh~8*`Z0T@O zu1%NQwI8%Sq)Vif4L6sC{RdJ9eR&fm`!asky^%MSAUbtq0sT(GD{nk!41AAH#EF)L z#^tDmsjrz771BX55|+{g$&~757suI8IMkN@;=Ul}{}iQylOS}sa8R8JU3ki3dScbp zInFN&CwgCbB$DX8C-LQ|?z)>1LF-?p@mEN6)AxLTq&FCQ8fLVRDL=O`1rp)v%M08= z(aso0=#S-V1qy7mj8wIQ@};!NlD`ZMqSnr|#f`h}(R$+gy^ETY=&J=swsU5(Ok0i7A>?tg4_d*a z4o7*Z-u}Jvb2wbO1@00|hPUFXGr+K;I}1%M-4XJjV!gHzN8HvS${9)@>`QEY?;Yr~ zMK>O;J&u}6Wn(?J{uz_3T;|W=7f^f^+H=l+JZMEszUu#!)#Hikj(rn*2vYP-+?CC_ zv~wk&?mbtQQFoZY8ALC#ja0Xf=AZ{{q1csj~&tY-f#sg zK)eeJ80QxEzPtbMlq`k!IHRo1?D5Ft%VPAweKh<*dhwaF!Y{nXjz=J;GwMyvetFj1 zS2X`Mc7Rp&ldC(Ue9(&XX)R7^P&Ux$;g(<`GWNIrA9$;(y9T*m_L^~fdh( #include #include -#include +#include #include - +#include #include namespace @@ -42,7 +42,10 @@ namespace app::powernap void PowerNapProgressPresenter::setTimer(std::unique_ptr &&_timer) { timer = std::move(_timer); - timer->registerOnFinishedCallback([this]() { onNapFinished(); }); + timer->registerOnFinishedCallback([this]() { + getView()->progressFinished(); + onNapFinished(); + }); } void PowerNapProgressPresenter::activate() @@ -66,15 +69,13 @@ namespace app::powernap void PowerNapProgressPresenter::pause() { timer->stop(); - app->switchWindow(gui::window::session_paused::sessionPaused); + getView()->pause(); } void PowerNapProgressPresenter::resume() { - if (napFinished) { - return; - } timer->start(); + getView()->resume(); } void PowerNapProgressPresenter::onNapFinished() @@ -119,4 +120,9 @@ namespace app::powernap getView()->setTimeFormat(timeModel->getTimeFormat()); } + bool PowerNapProgressPresenter::isTimerStopped() + { + return timer->isStopped(); + } + } // namespace app::powernap diff --git a/products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp b/products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp index 8970a135574b50e554e6992065d744a729762c92..19e56840473333d5f104de41f79c1d1753d2d35f 100644 --- a/products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp +++ b/products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapProgressPresenter.hpp @@ -45,6 +45,9 @@ namespace app::powernap virtual void napEnded() = 0; virtual void setTime(std::time_t newTime) = 0; virtual void setTimeFormat(utils::time::Locale::TimeFormat fmt) = 0; + virtual void progressFinished() = 0; + virtual void pause() = 0; + virtual void resume() = 0; }; class Presenter : public BasePresenter @@ -52,6 +55,7 @@ namespace app::powernap public: virtual void activate() = 0; virtual void endNap() = 0; + virtual bool isTimerStopped() = 0; virtual void pause() = 0; virtual void resume() = 0; virtual void setTimer(std::unique_ptr &&timer) = 0; @@ -74,6 +78,17 @@ namespace app::powernap sys::TimerHandle napAlarmTimer; bool napFinished{false}; + static constexpr auto endWindowTimeout = std::chrono::seconds{5}; + + public: + PowerNapProgressPresenter(app::ApplicationCommon *app, + settings::Settings *settings, + std::unique_ptr soundsRepository, + AbstractAudioModel &audioModel, + app::bell_settings::AbstractFrontlightModel &frontLightModel, + std::unique_ptr timeModel, + std::unique_ptr alarmLightOnOffModel); + void activate() override; void endNap() override; void pause() override; @@ -81,18 +96,10 @@ namespace app::powernap void setTimer(std::unique_ptr &&_timer) override; void handleUpdateTimeEvent() override; bool isNapFinished() override; + bool isTimerStopped() override; void onNapFinished(); void onNapAlarmFinished(); void onBeforeShow() override; - - public: - PowerNapProgressPresenter(app::ApplicationCommon *app, - settings::Settings *settings, - std::unique_ptr soundsRepository, - AbstractAudioModel &audioModel, - app::bell_settings::AbstractFrontlightModel &frontLightModel, - std::unique_ptr timeModel, - std::unique_ptr alarmLightOnOffModel); }; } // namespace app::powernap diff --git a/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp b/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp index a91e0d860b8d505714de7086519647b4cea5f78b..dc2f6ea9627b88bfbcf000cce17c9b95646573e8 100644 --- a/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp +++ b/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.cpp @@ -5,52 +5,11 @@ #include "application-bell-powernap/ApplicationBellPowerNap.hpp" #include "data/PowerNapStyle.hpp" #include "data/PowerNapSwitchData.hpp" -#include -#include #include -#include -#include #include namespace { - void decorateProgressItem(gui::Rect *item, gui::Alignment::Vertical alignment) - { - item->setEdges(gui::RectangleEdge::None); - item->activeItem = false; - item->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, alignment)); - } - void createTitle(gui::VBox *parent) - { - auto title = new gui::Text(parent, 0, 0, parent->getWidth(), parent->getHeight() / 2); - title->setFont(gui::powerNapStyle::descriptionFont); - title->setText(utils::translate("app_bellmain_power_nap")); - decorateProgressItem(title, gui::Alignment::Vertical::Top); - } - gui::HBarGraph *createProgress(gui::VBox *parent) - { - auto progressBox = new gui::HBox(parent, 0, 0, parent->getWidth(), parent->getHeight() / 2); - decorateProgressItem(progressBox, gui::Alignment::Vertical::Bottom); - auto progressBar = - new gui::HBarGraph(progressBox, 0, 0, gui::powerNapStyle::progress::boxesCount, gui::BarGraphStyle::Heavy); - decorateProgressItem(progressBar, gui::Alignment::Vertical::Center); - return progressBar; - } - gui::TimeFixedWidget *createTimer(gui::Item *parent) - { - using namespace style; - using namespace gui::powerNapStyle; - auto timer = new gui::TimeFixedWidget(parent, - 0, - 0, - bell_base_layout::outer_layouts_w, - bell_base_layout::outer_layouts_h - progress::bottomDescTopMargin); - timer->setFontAndDimensions(napTimerFont); - timer->setMargins(gui::Margins(0, progress::bottomDescTopMargin, 0, 0)); - decorateProgressItem(timer, gui::Alignment::Vertical::Top); - return timer; - } - inline constexpr auto powernapTimerName = "PowerNapTimer"; inline constexpr std::chrono::seconds timerTick{1}; } // namespace @@ -58,10 +17,11 @@ namespace namespace gui { PowerNapProgressWindow::PowerNapProgressWindow( - app::ApplicationCommon *app, std::shared_ptr presenter) - : AppWindow(app, gui::window::name::powernapProgress), presenter{std::move(presenter)} + app::ApplicationCommon *app, + std::shared_ptr &&windowPresenter) + : AppWindow(app, gui::window::name::powernapProgress), presenter{std::move(windowPresenter)} { - this->presenter->attach(this); + presenter->attach(this); buildInterface(); } @@ -69,50 +29,89 @@ namespace gui { AppWindow::buildInterface(); + statusBar->setVisible(false); + header->setTitleVisibility(false); + navBar->setVisible(false); + buildLayout(); configureTimer(); - // presenter->activate(); } + void PowerNapProgressWindow::buildLayout() { - statusBar->setVisible(false); - auto body = new gui::BellBaseLayout(this, 0, 0, style::bell_base_layout::w, style::bell_base_layout::h, false); - auto vBox = - new VBox(body->getCenterBox(), 0, 0, style::bell_base_layout::w, style::bell_base_layout::center_layout_h); - decorateProgressItem(vBox, gui::Alignment::Vertical::Top); - createTitle(vBox); - progressBar = createProgress(vBox); - timerText = createTimer(body->lastBox); - - time = new BellStatusClock(body->firstBox); - time->setMaximumSize(body->firstBox->getWidth(), body->firstBox->getHeight()); - time->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top)); - body->firstBox->resizeItems(); - - dimensionChangedCallback = [&](Item &, const BoundingBox &newDim) -> bool { - body->setArea({0, 0, newDim.w, newDim.h}); - return true; - }; + using namespace gui::powerNapStyle; + const auto progressArcRadius = pnStyle::progress::radius; + const auto progressArcWidth = pnStyle::progress::penWidth; + const auto arcStartAngle = -90 - pnStyle::progress::verticalDeviationDegrees; + const auto arcSweepAngle = 360 - (2 * pnStyle::progress::verticalDeviationDegrees); + const auto arcProgressSteps = 1000; + + Arc::ShapeParams arcParams; + arcParams.setCenterPoint(Point(getWidth() / 2, getHeight() / 2)) + .setRadius(progressArcRadius) + .setStartAngle(arcStartAngle) // Start drawing the circle from top. + .setSweepAngle(arcSweepAngle) + .setPenWidth(progressArcWidth) + .setBorderColor(ColorFullBlack); + + progress = new ArcProgressBar(this, arcParams, ArcProgressBar::ProgressDirection::CounterClockwise); + progress->setMaximum(arcProgressSteps); + + mainVBox = new VBox(this, 0, 0, style::window_width, style::window_height); + + clock = new BellStatusClock(mainVBox); + clock->setMaximumSize(pnStyle::clock::maxSizeX, pnStyle::clock::maxSizeY); + clock->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); + clock->setMargins(gui::Margins(0, pnStyle::clock::marginTop, 0, 0)); + + timer = new gui::TimeFixedWidget(mainVBox, 0, 0, pnStyle::timer::maxSizeX, pnStyle::timer::maxSizeY, true); + timer->setFontAndDimensions(pnStyle::timer::font); + timer->setMinimumSize(pnStyle::timer::maxSizeX, pnStyle::timer::maxSizeY); + timer->setMargins(gui::Margins(0, pnStyle::timer::marginTop, pnStyle::timer::marginRight, 0)); + timer->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); + + iconPause = new Icon(mainVBox, 0, 0, 0, 0, {}, {}); + iconPause->setMinimumSize(pnStyle::pauseIcon::maxSizeX, pnStyle::pauseIcon::maxSizeY); + iconPause->setMargins(gui::Margins(0, pnStyle::pauseIcon::marginTop, 0, 0)); + iconPause->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); + iconPause->image->set(pnStyle::pauseIcon::image, ImageTypeSpecifier::W_G); + iconPause->setVisible(false); + + iconRing = new Icon(mainVBox, 0, 0, 0, 0, {}, {}); + iconRing->setMinimumSize(pnStyle::ringIcon::maxSizeX, pnStyle::ringIcon::maxSizeY); + iconRing->setMargins(gui::Margins(0, pnStyle::ringIcon::marginTop, 0, 0)); + iconRing->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); + iconRing->image->set(pnStyle::ringIcon::image, ImageTypeSpecifier::W_G); + iconRing->setVisible(false); + + mainVBox->resizeItems(); } + void PowerNapProgressWindow::configureTimer() { - auto timer = std::make_unique( + auto progressTimer = std::make_unique( application, *this, powernapTimerName, timerTick, app::ProgressCountdownMode::Increasing); - timer->attach(progressBar); - timer->attach(timerText); - presenter->setTimer(std::move(timer)); + progressTimer->attach(progress); + progressTimer->attach(timer); + presenter->setTimer(std::move(progressTimer)); } - auto PowerNapProgressWindow::onInput(const InputEvent &inputEvent) -> bool + bool PowerNapProgressWindow::onInput(const InputEvent &inputEvent) { if (inputEvent.isShortRelease()) { const auto key = mapKey(inputEvent.getKeyCode()); - if (presenter->isNapFinished() && key == KeyMap::LightPress) { + if (presenter->isNapFinished() && + (key == KeyMap::LightPress || key == KeyMap::DeepPressDown || key == KeyMap::DeepPressUp)) { presenter->endNap(); return true; } else if (not presenter->isNapFinished() && key == KeyMap::LightPress) { - presenter->pause(); + if (presenter->isTimerStopped()) { + presenter->resume(); + } + else { + presenter->pause(); + } return true; } else if (not presenter->isNapFinished() && key == KeyMap::Back) { @@ -132,13 +131,13 @@ namespace gui void PowerNapProgressWindow::setTime(std::time_t newTime) { - time->setTime(newTime); - time->setTimeFormatSpinnerVisibility(true); + clock->setTime(newTime); + clock->setTimeFormatSpinnerVisibility(true); } void PowerNapProgressWindow::setTimeFormat(utils::time::Locale::TimeFormat fmt) { - time->setTimeFormat(fmt); + clock->setTimeFormat(fmt); } RefreshModes PowerNapProgressWindow::updateTime() @@ -149,16 +148,36 @@ namespace gui return RefreshModes::GUI_REFRESH_FAST; } + void PowerNapProgressWindow::pause() + { + timer->setVisible(false); + iconPause->setVisible(true); + mainVBox->resizeItems(); + } + + void PowerNapProgressWindow::resume() + { + timer->setVisible(true); + iconPause->setVisible(false); + mainVBox->resizeItems(); + } + + void PowerNapProgressWindow::progressFinished() + { + timer->setVisible(false); + iconPause->setVisible(false); + iconRing->setVisible(true); + mainVBox->resizeItems(); + } + void PowerNapProgressWindow::onBeforeShow(ShowMode mode, SwitchData *data) { + AppWindow::onBeforeShow(mode, data); presenter->onBeforeShow(); updateTime(); if (mode == ShowMode::GUI_SHOW_INIT) { presenter->activate(); } - else { - presenter->resume(); - } } } // namespace gui diff --git a/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp b/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp index e85ee59ce7d04d59edb2c0982e7ed2ce15a7e974..8f7a594eaea7f9c03afef06910efdd26ba39e832 100644 --- a/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp +++ b/products/BellHybrid/apps/application-bell-powernap/windows/PowerNapProgressWindow.hpp @@ -4,37 +4,47 @@ #pragma once #include "presenter/PowerNapProgressPresenter.hpp" -#include +#include #include +#include +#include #include +#include +#include +#include namespace gui { - class HBarGraph; class Text; class PowerNapProgressWindow : public AppWindow, public app::powernap::PowerNapProgressContract::View { - std::shared_ptr presenter; - gui::HBarGraph *progressBar = nullptr; - gui::TimeFixedWidget *timerText = nullptr; - gui::BellStatusClock *time = nullptr; + public: + PowerNapProgressWindow(app::ApplicationCommon *app, + std::shared_ptr &&windowPresenter); + // virtual methods + void onBeforeShow(ShowMode mode, SwitchData *data) override; + bool onInput(const InputEvent &inputEvent) override; void buildInterface() override; - auto onInput(const InputEvent &inputEvent) -> bool override; + void progressFinished() override; + void pause() override; + void resume() override; + + private: + std::shared_ptr presenter; + gui::VBox *mainVBox = nullptr; + gui::ArcProgressBar *progress = nullptr; + gui::TimeFixedWidget *timer = nullptr; + gui::BellStatusClock *clock = nullptr; + gui::Icon *iconPause = nullptr; + gui::Icon *iconRing = nullptr; void setTime(std::time_t newTime); void setTimeFormat(utils::time::Locale::TimeFormat fmt); RefreshModes updateTime() override; - void buildLayout(); void configureTimer(); void napEnded() override; - - void onBeforeShow(ShowMode mode, SwitchData *data) override; - - public: - PowerNapProgressWindow(app::ApplicationCommon *app, - std::shared_ptr presenter); }; } // namespace gui diff --git a/products/BellHybrid/assets/assets_common.json b/products/BellHybrid/assets/assets_common.json index 425d8bad1fe1722b4160c19895c94d12c9b6d2d3..0bb04f724fe877b7faf0c5f76cc4118c37a0b3aa 100644 --- a/products/BellHybrid/assets/assets_common.json +++ b/products/BellHybrid/assets/assets_common.json @@ -52,6 +52,7 @@ {"name": "release.tgz", "tarfile" :"image/assets/images/bell/button_rotate_W_G.vpi", "output": "assets/images/bell/button_rotate_W_G.vpi"}, {"name": "release.tgz", "tarfile" :"image/assets/images/bell/alarm_colon_select_W_M.vpi", "output": "assets/images/bell/alarm_colon_select_W_M.vpi"}, {"name": "release.tgz", "tarfile" :"image/assets/images/bell/bell_arrow_down_W_M.vpi", "output": "assets/images/bell/bell_arrow_down_W_M.vpi"}, + {"name": "release.tgz", "tarfile" :"image/assets/images/bell/big_bell_ringing_W_G.vpi", "output": "assets/images/bell/big_bell_ringing_W_G.vpi"}, {"name": "release_audio.tgz", "tarfile" :"./image/assets/audio/bell/chimes/Blissful_Dream.mp3", "output": "assets/audio/chimes/Blissful_Dream.mp3"},