From 46bdedf9cd614f843a48cfc677d554154c2a1f68 Mon Sep 17 00:00:00 2001 From: Mateusz Piesta Date: Tue, 15 Mar 2022 13:14:56 +0100 Subject: [PATCH] [BH-1350] Meditation timer update Meditation timer application update. Refactored gui spinners, list items. --- image/assets/lang/Deutsch.json | 3 +- image/assets/lang/English.json | 13 +- image/assets/lang/Espanol.json | 3 +- image/assets/lang/Francais.json | 3 +- image/assets/lang/Polski.json | 10 +- module-apps/apps-common/CMakeLists.txt | 2 - .../apps-common/widgets/TextSpinnerBox.cpp | 14 +- .../apps-common/widgets/TextSpinnerBox.hpp | 8 +- .../apps-common/widgets/TimeSetFmtSpinner.cpp | 12 +- .../apps-common/widgets/TimeSetFmtSpinner.hpp | 2 +- .../apps-common/widgets/TimeSetSpinner.cpp | 19 +- .../widgets/spinners/GenericSpinner.hpp | 160 ------- .../widgets/spinners/ItemSpinner.hpp | 87 ++-- .../apps-common/widgets/spinners/Model.hpp | 212 +++++++++ .../widgets/spinners/SpinnerContents.hpp | 58 --- .../widgets/spinners/SpinnerPolicies.hpp | 410 ------------------ .../apps-common/widgets/spinners/Spinners.hpp | 29 +- .../widgets/spinners/StringOutputSpinner.hpp | 237 ++++++++++ module-apps/tests/CMakeLists.txt | 1 + module-apps/tests/test-Model.cpp | 199 +++++++++ .../board/rt1051/bsp/audio/CodecMAX98090.hpp | 6 +- products/BellHybrid/BellHybridMain.cpp | 5 +- .../windows/BGSoundsTimerSelectWindow.cpp | 12 +- .../windows/BGSoundsTimerSelectWindow.hpp | 2 +- .../windows/BGSoundsVolumeWindow.cpp | 12 +- .../windows/BellMainMenuWindow.cpp | 4 +- .../ApplicationBellMeditationTimer.cpp | 87 ---- .../CMakeLists.txt | 17 +- .../MeditationTimer.cpp | 114 +++++ .../data/Contract.hpp | 27 ++ .../data/MeditationCommon.hpp | 8 +- .../ApplicationBellMeditationTimer.hpp | 52 --- .../MeditationTimer.hpp | 55 +++ .../models/ChimeInterval.cpp | 40 ++ .../models/ChimeInterval.hpp | 19 + .../models/ChimeVolume.cpp | 18 + .../models/ChimeVolume.hpp | 18 + .../models/StartDelay.cpp | 27 ++ .../models/StartDelay.hpp | 18 + .../presenter/IntervalChimePresenter.cpp | 104 ----- .../presenter/IntervalChimePresenter.hpp | 54 --- .../presenter/MeditationProgressPresenter.cpp | 21 +- .../presenter/MeditationProgressPresenter.hpp | 11 +- .../presenter/MeditationTimerPresenter.cpp | 14 +- .../presenter/MeditationTimerPresenter.hpp | 16 +- .../presenter/ReadyGoingPresenter.cpp | 13 +- .../presenter/ReadyGoingPresenter.hpp | 12 +- .../presenter/SettingsPresenter.cpp | 117 +++++ .../presenter/SettingsPresenter.hpp | 44 ++ .../presenter/StatisticsPresenter.cpp | 22 + .../presenter/StatisticsPresenter.hpp | 23 + .../windows/IntervalChimeWindow.cpp | 83 ---- .../windows/IntervalChimeWindow.hpp | 36 -- .../windows/MeditationMainWindow.cpp | 58 +++ .../windows/MeditationMainWindow.hpp | 20 + .../windows/MeditationRunningWindow.cpp | 5 +- .../windows/MeditationTimerWindow.cpp | 22 +- .../windows/MeditationTimerWindow.hpp | 13 +- .../windows/ReadyGoingWindow.cpp | 16 +- .../windows/SettingsWindow.cpp | 67 +++ .../windows/SettingsWindow.hpp | 33 ++ .../windows/StatisticsWindow.cpp | 62 +++ .../windows/StatisticsWindow.hpp | 33 ++ .../data/PowerNapListItem.cpp | 10 +- .../ApplicationBellSettings.cpp | 2 +- .../models/FrontlightListItemProvider.cpp | 23 +- .../AlarmSettingsListItemProvider.cpp | 27 +- .../BedtimeSettingsListItemProvider.cpp | 28 +- .../PrewakeUpListItemProvider.cpp | 53 +-- .../alarm_settings/SnoozeListItemProvider.cpp | 83 ++-- .../alarm_settings/SnoozeSettingsModel.cpp | 5 +- .../presenter/BedtimeSettingsPresenter.cpp | 20 +- .../presenter/BedtimeSettingsPresenter.hpp | 10 +- .../widgets/TemperatureUnitListItem.cpp | 11 +- .../widgets/TemperatureUnitListItem.hpp | 2 +- .../widgets/TimeFormatSetListItem.cpp | 14 +- .../widgets/TimeFormatSetListItem.hpp | 2 +- .../windows/BellSettingsBedtimeToneWindow.cpp | 2 +- .../windows/BellSettingsBedtimeToneWindow.hpp | 5 +- .../windows/BellSettingsLanguageWindow.cpp | 10 +- .../windows/BellSettingsLanguageWindow.hpp | 2 +- .../include/common/BellListItemProvider.hpp | 11 + .../common/include/common/LanguageUtils.hpp | 3 +- .../include/common/widgets/ListItems.hpp | 66 +-- .../common/widgets/list_items/Fraction.hpp | 60 +++ .../widgets/list_items/NumberWithSuffix.hpp | 45 ++ .../common/widgets/list_items/Numeric.hpp | 22 + .../common/widgets/list_items/OnOff.hpp | 30 ++ .../common/widgets/list_items/Text.hpp | 24 + .../common/widgets/list_items/details.hpp | 106 +++++ .../apps/common/src/LanguageUtils.cpp | 34 +- .../apps/common/src/models/SettingsModel.cpp | 3 + .../apps/common/src/widgets/ListItems.cpp | 151 +------ .../src/widgets/TimeSetSpinnerVertical.cpp | 44 +- 94 files changed, 2227 insertions(+), 1603 deletions(-) delete mode 100644 module-apps/apps-common/widgets/spinners/GenericSpinner.hpp create mode 100644 module-apps/apps-common/widgets/spinners/Model.hpp delete mode 100644 module-apps/apps-common/widgets/spinners/SpinnerContents.hpp delete mode 100644 module-apps/apps-common/widgets/spinners/SpinnerPolicies.hpp create mode 100644 module-apps/apps-common/widgets/spinners/StringOutputSpinner.hpp create mode 100644 module-apps/tests/test-Model.cpp delete mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/ApplicationBellMeditationTimer.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp delete mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.hpp delete mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp delete mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.hpp delete mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.cpp delete mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationMainWindow.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationMainWindow.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/SettingsWindow.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/SettingsWindow.hpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/StatisticsWindow.cpp create mode 100644 products/BellHybrid/apps/application-bell-meditation-timer/windows/StatisticsWindow.hpp create mode 100644 products/BellHybrid/apps/common/include/common/widgets/list_items/Fraction.hpp create mode 100644 products/BellHybrid/apps/common/include/common/widgets/list_items/NumberWithSuffix.hpp create mode 100644 products/BellHybrid/apps/common/include/common/widgets/list_items/Numeric.hpp create mode 100644 products/BellHybrid/apps/common/include/common/widgets/list_items/OnOff.hpp create mode 100644 products/BellHybrid/apps/common/include/common/widgets/list_items/Text.hpp create mode 100644 products/BellHybrid/apps/common/include/common/widgets/list_items/details.hpp diff --git a/image/assets/lang/Deutsch.json b/image/assets/lang/Deutsch.json index ff5fbfa8d4a36951c977fb355c7f7d0dde51a27e..c5c5fdca1273c909dcba323fbfb8fc2ef37899e8 100644 --- a/image/assets/lang/Deutsch.json +++ b/image/assets/lang/Deutsch.json @@ -678,10 +678,9 @@ "app_bell_settings_factory_reset": "Zurücksetzen", "app_bell_settings_display_factory_reset_confirmation": "Zurücksetzen?", "app_bell_meditation_timer": "Meditation", - "app_bell_meditation_interval_chime": "Intervallschall", + "app_bell_meditation_chime_interval": "Intervallschall", "app_bell_meditation_progress": "Meditation", "app_bell_meditation_interval_none": "kein", - "app_bell_meditation_interval_every_x_minutes": "jede %0", "app_bell_meditation_put_down_and_wait": "Legen Sie Mudita Harmony
ab und warten Sie auf den Gong
", "app_bell_meditation_thank_you_for_session": "Danke für
die Sitzung
" } diff --git a/image/assets/lang/English.json b/image/assets/lang/English.json index 1b0fe673df236dbb96bd3be5dbb68ccbdc7bad19..105ce8b538321598c4094f41442caa6859941ee1 100644 --- a/image/assets/lang/English.json +++ b/image/assets/lang/English.json @@ -83,6 +83,10 @@ "common_minutes_lower": "minutes", "common_minutes_lower_genitive": "minutes", "common_minute_short": "min", + "common_second_lower": "second", + "common_seconds_lower": "seconds", + "common_seconds_lower_genitive": "seconds", + "common_second_short": "sec", "common_paused": "Paused", "common_text_copy": "Copy text", "common_text_paste": "Paste text", @@ -610,10 +614,15 @@ "app_bellmain_settings": "Settings", "app_bellmain_main_window_title": "Mudita Harmony", "app_bell_meditation_timer": "Meditation", - "app_bell_meditation_interval_chime": "Interval chime", + "app_bell_meditation_settings": "Settings", + "app_bell_meditation_start": "Meditate now", + "app_bell_meditation_statistics": "Statistics", + "app_bell_meditation_chime_volume": "Chime volume", + "app_bell_meditation_chime_interval": "Chime interval", + "app_bell_meditation_chime_interval_bottom": "of the meditation", + "app_bell_meditation_start_delay": "Start delay", "app_bell_meditation_progress": "Meditation timer", "app_bell_meditation_interval_none": "None", - "app_bell_meditation_interval_every_x_minutes": "every %0", "app_bell_meditation_put_down_and_wait": "Put down Mudita Harmony
and wait for the gong
", "app_bell_meditation_thank_you_for_session": "Thank you for
the session
", "app_bell_onboarding_welcome_message": "Mudita Harmony
is switched OFF
", diff --git a/image/assets/lang/Espanol.json b/image/assets/lang/Espanol.json index 91f537442fb73532f0072a0965e6d2716c5574db..16d18413be0ae19790f3020744708395f6b083f4 100644 --- a/image/assets/lang/Espanol.json +++ b/image/assets/lang/Espanol.json @@ -678,10 +678,9 @@ "app_bell_settings_factory_reset": "Restablecer", "app_bell_settings_display_factory_reset_confirmation": "¿Restablecer la configuración?", "app_bell_meditation_timer": "Meditación", - "app_bell_meditation_interval_chime": "Intervalo", + "app_bell_meditation_chime_interval": "Intervalo", "app_bell_meditation_progress": "Meditación", "app_bell_meditation_interval_none": "Ninguno", - "app_bell_meditation_interval_every_x_minutes": "cada %0", "app_bell_meditation_put_down_and_wait": "Posicione Mudita Harmony
y espere el gong
", "app_bell_meditation_thank_you_for_session": "Gracias
por la sesión
" } diff --git a/image/assets/lang/Francais.json b/image/assets/lang/Francais.json index af0a200ed2002bf6dcf9881e9ae996c48f373b76..49761b49200bcb4f314f4c58e407cf399f53438b 100644 --- a/image/assets/lang/Francais.json +++ b/image/assets/lang/Francais.json @@ -648,10 +648,9 @@ "app_bell_settings_factory_reset": "Réinitialisation", "app_bell_settings_display_factory_reset_confirmation": "Rétablir

la configuration ?
", "app_bell_meditation_timer": "Méditation", - "app_bell_meditation_interval_chime": "gong intervalle", + "app_bell_meditation_chime_interval": "gong intervalle", "app_bell_meditation_progress": "Méditation", "app_bell_meditation_interval_none": "Aucune", - "app_bell_meditation_interval_every_x_minutes": "toutes les %0", "app_bell_meditation_put_down_and_wait": "Posez Mudita Harmony
et attendez le gong
", "app_bell_meditation_thank_you_for_session": "Merci
pour cette session
" } diff --git a/image/assets/lang/Polski.json b/image/assets/lang/Polski.json index 500b2c77aaf44fff3f4d1d3288a8805a796f9a47..fa5cd6b1ee85fdc1084f049bb18b60b882920c9e 100644 --- a/image/assets/lang/Polski.json +++ b/image/assets/lang/Polski.json @@ -80,6 +80,10 @@ "common_minutes_lower": "minuty", "common_minutes_lower_genitive": "minut", "common_minute_short": "min", + "common_second_lower": "sekunda", + "common_seconds_lower": "sekundy", + "common_seconds_lower_genitive": "sekund", + "common_second_short": "sec", "common_paused": "Pauza", "common_text_copy": "Kopiuj tekst", "common_text_paste": "Wklej tekst", @@ -691,10 +695,10 @@ "app_bell_settings_about_info_title": "Instrukcja i informacje dot. certyfikacji", "app_bell_settings_about_info_text": "www.mudita.com", "app_bell_meditation_timer": "Medytacja", - "app_bell_meditation_interval_chime": "Dzwonek interwału", + "app_bell_meditation_chime_interval": "Dzwonek interwału", "app_bell_meditation_progress": "Medytacja", "app_bell_meditation_interval_none": "Brak", - "app_bell_meditation_interval_every_x_minutes": "co %0", "app_bell_meditation_put_down_and_wait": "Odłóż Mudita Harmony
i czekaj na gong
", - "app_bell_meditation_thank_you_for_session": "Dziękujemy
za sesję
" + "app_bell_meditation_thank_you_for_session": "Dziękujemy
za sesję
", + "app_bell_meditation_statistics": "Statystyki" } diff --git a/module-apps/apps-common/CMakeLists.txt b/module-apps/apps-common/CMakeLists.txt index 9b4691d25b8b1f16618c320aa64ea206743db55f..3144559889d0ca09701f8b1e0207d647a7463144 100644 --- a/module-apps/apps-common/CMakeLists.txt +++ b/module-apps/apps-common/CMakeLists.txt @@ -79,9 +79,7 @@ target_sources(apps-common models/SongsRepository.hpp models/SongsModelInterface.hpp - widgets/spinners/GenericSpinner.hpp widgets/spinners/ItemSpinner.hpp - widgets/spinners/SpinnerPolicies.hpp widgets/spinners/Spinners.hpp ) diff --git a/module-apps/apps-common/widgets/TextSpinnerBox.cpp b/module-apps/apps-common/widgets/TextSpinnerBox.cpp index 124bb3b42766433ae6264234cd0fda4a652597c4..727e613179527e67c5567ed90d810c272dfa0c6e 100644 --- a/module-apps/apps-common/widgets/TextSpinnerBox.cpp +++ b/module-apps/apps-common/widgets/TextSpinnerBox.cpp @@ -5,7 +5,7 @@ namespace gui { - TextSpinnerBox::TextSpinnerBox(Item *parent, const std::vector &data, Boundaries boundaries) : HBox(parent) + TextSpinnerBox::TextSpinnerBox(Item *parent, std::vector data, Boundaries boundaries) : HBox(parent) { setEdges(RectangleEdge::Bottom); @@ -13,7 +13,7 @@ namespace gui leftArrow->setMinimumSizeToFitImage(); leftArrow->setVisible(false); - spinner = new UTF8Spinner(data, Boundaries::Continuous, Orientation::Horizontal); + spinner = new StringSpinner(std::move(data), boundaries, Orientation::Horizontal); spinner->setFont(style::window::font::medium); spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); spinner->setEdges(RectangleEdge::All); @@ -27,13 +27,13 @@ namespace gui inputCallback = [&](Item &item, const InputEvent &event) { return spinner->onInput(event); }; focusChangedCallback = [&](gui::Item &item) { - if (focus && !spinner->isSingle()) { + if (focus && spinner->size() != 1) { leftArrow->setVisible(true); rightArrow->setVisible(true); spinner->setFont(style::window::font::mediumbold); setPenWidth(style::window::default_border_focus_w); } - else if (focus && spinner->isSingle()) { + else if (focus && spinner->size() == 1) { leftArrow->setVisible(false); rightArrow->setVisible(false); spinner->setFont(style::window::font::mediumbold); @@ -58,16 +58,16 @@ namespace gui void TextSpinnerBox::setData(const std::vector &data) { - spinner->setRange(data); + spinner->set_range(data); } UTF8 TextSpinnerBox::getCurrentValue() const noexcept { - return spinner->getCurrentValue(); + return spinner->value(); } void TextSpinnerBox::setCurrentValue(UTF8 val) { - spinner->setCurrentValue(val); + spinner->set_value(val); } } // namespace gui diff --git a/module-apps/apps-common/widgets/TextSpinnerBox.hpp b/module-apps/apps-common/widgets/TextSpinnerBox.hpp index 2a0ce27d5b38b60a1d85be4b72cce5cabfb0513d..697572d7c0c8612b3e2a82354f33216cafd43c68 100644 --- a/module-apps/apps-common/widgets/TextSpinnerBox.hpp +++ b/module-apps/apps-common/widgets/TextSpinnerBox.hpp @@ -14,14 +14,14 @@ namespace gui class TextSpinnerBox : public HBox { public: - TextSpinnerBox(Item *parent, const std::vector &data, Boundaries boundaries); + TextSpinnerBox(Item *parent, std::vector data, Boundaries boundaries); void setData(const std::vector &data); [[nodiscard]] UTF8 getCurrentValue() const noexcept; void setCurrentValue(UTF8 val); private: - UTF8Spinner *spinner = nullptr; - ImageBox *leftArrow = nullptr; - ImageBox *rightArrow = nullptr; + StringSpinner *spinner = nullptr; + ImageBox *leftArrow = nullptr; + ImageBox *rightArrow = nullptr; }; } // namespace gui diff --git a/module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp b/module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp index 26eb092abf6bf999f3db6931ce6e3e1f4d66354d..dd89d971e946c2e158cdcea55bc158ec5dc4f34d 100644 --- a/module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp +++ b/module-apps/apps-common/widgets/TimeSetFmtSpinner.cpp @@ -24,8 +24,8 @@ namespace gui timeSetSpinner->setFont(focusFontName, noFocusFontName); timeSetSpinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); - auto textRange = UTF8Spinner::Range{time::Locale::getAM(), time::Locale::getPM()}; - fmt = new UTF8Spinner(textRange, Boundaries::Continuous); + auto textRange = StringSpinner::range{time::Locale::getAM(), time::Locale::getPM()}; + fmt = new StringSpinner(textRange, Boundaries::Continuous); updateFmtFont(noFocusFontName); fmt->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); fmt->setMargins(getFmtMargins(noFocusFontName)); @@ -74,10 +74,10 @@ namespace gui if (timeFormat != newFormat) { timeSetSpinner->setHour(date::make12(hours).count()); if (date::is_pm(hours)) { - fmt->setCurrentValue(time::Locale::getPM()); + fmt->set_value(time::Locale::getPM()); } else { - fmt->setCurrentValue(time::Locale::getAM()); + fmt->set_value(time::Locale::getAM()); } } @@ -215,7 +215,7 @@ namespace gui auto TimeSetFmtSpinner::isPM() const noexcept -> bool { - return fmt->getCurrentValue() == utils::time::Locale::getPM().c_str(); + return fmt->value() == utils::time::Locale::getPM().c_str(); } auto TimeSetFmtSpinner::getTimeFormat() const noexcept -> utils::time::Locale::TimeFormat @@ -234,7 +234,7 @@ namespace gui const auto hours = std::chrono::hours{t->tm_hour}; const auto time12H = date::make12(hours); const auto isPM = date::is_pm(hours); - fmt->setCurrentValue(isPM ? utils::time::Locale::getPM() : utils::time::Locale::getAM()); + fmt->set_value(isPM ? utils::time::Locale::getPM() : utils::time::Locale::getAM()); timeSetSpinner->setTime(time12H.count(), t->tm_min); } } diff --git a/module-apps/apps-common/widgets/TimeSetFmtSpinner.hpp b/module-apps/apps-common/widgets/TimeSetFmtSpinner.hpp index 4952687ee29fedff053a86458229aaa42dda7a03..6ae08449706b2507f0ae993d235747d5cebac69e 100644 --- a/module-apps/apps-common/widgets/TimeSetFmtSpinner.hpp +++ b/module-apps/apps-common/widgets/TimeSetFmtSpinner.hpp @@ -76,7 +76,7 @@ namespace gui void handleContentChanged() override; TimeSetSpinner *timeSetSpinner = nullptr; - UTF8Spinner *fmt = nullptr; + StringSpinner *fmt = nullptr; EditMode editMode = EditMode::Edit; std::string focusFontName = style::window::font::supersizeme; std::string noFocusFontName = style::window::font::supersizemelight; diff --git a/module-apps/apps-common/widgets/TimeSetSpinner.cpp b/module-apps/apps-common/widgets/TimeSetSpinner.cpp index dd044c751edfbe3ce50d25901149acedbe4b4103..9800308eae37d6ba148b33ff94e330899c90fc40 100644 --- a/module-apps/apps-common/widgets/TimeSetSpinner.cpp +++ b/module-apps/apps-common/widgets/TimeSetSpinner.cpp @@ -26,13 +26,13 @@ namespace gui setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); setEdges(RectangleEdge::None); - hour = new UIntegerSpinner(UIntegerSpinner::Range{hourMin, hourMax, hourStep}, Boundaries::Continuous); + hour = new UIntegerSpinner(UIntegerSpinner::range{hourMin, hourMax, hourStep}, Boundaries::Continuous); updateFont(hour, noFocusFontName); hour->setAlignment(Alignment(Alignment::Horizontal::Right, Alignment::Vertical::Center)); hour->setEdges(RectangleEdge::None); hour->setPenFocusWidth(style::time_set_spinner::focus::size); - hour->setCurrentValue(0); + hour->set_value(0); addWidget(hour); @@ -42,14 +42,14 @@ namespace gui colon->setEdges(RectangleEdge::None); colon->activeItem = false; - minute = new UIntegerSpinnerFixed(UIntegerSpinnerFixed::Range{minuteMin, minuteMax, minuteStep}, + minute = new UIntegerSpinnerFixed(UIntegerSpinnerFixed::range{minuteMin, minuteMax, minuteStep}, Boundaries::Continuous); updateFont(minute, noFocusFontName); minute->setPenFocusWidth(style::time_set_spinner::focus::size); minute->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center)); minute->setEdges(RectangleEdge::None); - minute->setCurrentValue(0); + minute->set_value(0); addWidget(minute); resizeItems(); @@ -133,12 +133,12 @@ namespace gui auto TimeSetSpinner::setHour(int value) noexcept -> void { - hour->setCurrentValue(value); + hour->set_value(value); } auto TimeSetSpinner::setMinute(int value) noexcept -> void { - minute->setCurrentValue(value); + minute->set_value(value); } auto TimeSetSpinner::setFont(const std::string &newFontName) noexcept -> void @@ -186,12 +186,12 @@ namespace gui auto TimeSetSpinner::getHour() const noexcept -> int { - return hour->getCurrentValue(); + return hour->value(); } auto TimeSetSpinner::getMinute() const noexcept -> int { - return minute->getCurrentValue(); + return minute->value(); } void TimeSetSpinner::updateFocus(Item *newFocus) @@ -220,7 +220,8 @@ namespace gui auto TimeSetSpinner::setHourRange(std::uint32_t min, std::uint32_t max) -> void { - hour->setRange(UIntegerSpinner::Range{min, max, hourStep}); + hour->set_range( + UIntegerSpinner::range{static_cast(min), static_cast(max), hourStep}); } auto TimeSetSpinner::getColonImage(const std::string &colonFont) const noexcept -> std::string diff --git a/module-apps/apps-common/widgets/spinners/GenericSpinner.hpp b/module-apps/apps-common/widgets/spinners/GenericSpinner.hpp deleted file mode 100644 index c346f875bbf7af6c3d4d7b5941712d2f9a3e5dd5..0000000000000000000000000000000000000000 --- a/module-apps/apps-common/widgets/spinners/GenericSpinner.hpp +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include "SpinnerPolicies.hpp" -#include - -namespace gui -{ - template class GenericSpinner : public TextFixedSize - { - public: - using Range = typename Policy::Range; - using Type = typename Policy::Type; - - using OnValueChanged = std::function; - - explicit GenericSpinner(Range range, - Boundaries boundaries = Boundaries::Continuous, - Orientation orientation = Orientation::Vertical); - - [[nodiscard]] Type getCurrentValue() const noexcept; - void setCurrentValue(Type val); - void setRange(Range range); - - void setFocusEdges(RectangleEdge edges); - bool onInput(const InputEvent &inputEvent) override; - bool onFocus(bool state) override; - [[nodiscard]] bool isSingle() const; - [[nodiscard]] bool isAtMin() const; - [[nodiscard]] bool isAtMax() const; - - OnValueChanged onValueChanged; - - private: - void stepNext(); - void stepPrevious(); - bool isPreviousEvent(const InputEvent &inputEvent); - bool isNextEvent(const InputEvent &inputEvent); - void update(); - void invoke(); - - Policy policy; - RectangleEdge focusEdges = RectangleEdge::Bottom; - Orientation orientation = Orientation::Vertical; - }; - - template - GenericSpinner::GenericSpinner(GenericSpinner::Range range, - Boundaries boundaries, - Orientation orientation) - : policy{range, boundaries}, orientation(orientation) - { - setEditMode(EditMode::Browse); - drawUnderline(false); - update(); - } - - template void GenericSpinner::setFocusEdges(RectangleEdge edges) - { - focusEdges = edges; - } - - template void GenericSpinner::setRange(Range range) - { - policy.updateRange(range); - update(); - } - - template void GenericSpinner::setCurrentValue(const Type val) - { - policy.set(val); - update(); - } - - template - typename GenericSpinner::Type GenericSpinner::getCurrentValue() const noexcept - { - return policy.get(); - } - - template bool GenericSpinner::isPreviousEvent(const InputEvent &inputEvent) - { - return (orientation == Orientation::Vertical && inputEvent.is(KeyCode::KEY_DOWN)) || - (orientation == Orientation::Horizontal && inputEvent.is(KeyCode::KEY_LEFT)); - } - - template bool GenericSpinner::isNextEvent(const InputEvent &inputEvent) - { - return (orientation == Orientation::Vertical && inputEvent.is(KeyCode::KEY_UP)) || - (orientation == Orientation::Horizontal && inputEvent.is(KeyCode::KEY_RIGHT)); - } - - template bool GenericSpinner::onInput(const InputEvent &inputEvent) - { - if (inputEvent.isShortRelease()) { - if (isPreviousEvent(inputEvent)) { - stepPrevious(); - return true; - } - else if (isNextEvent(inputEvent)) { - stepNext(); - return true; - } - } - return false; - } - - template bool GenericSpinner::onFocus(bool state) - { - if (focus) { - setEdges(focusEdges); - } - else { - setEdges(RectangleEdge::None); - } - showCursor(state); - return true; - } - - template void GenericSpinner::stepNext() - { - if (policy.next()) { - update(); - invoke(); - } - } - - template void GenericSpinner::stepPrevious() - { - if (policy.previous()) { - update(); - invoke(); - } - } - - template void GenericSpinner::update() - { - setText(policy.str()); - } - template void GenericSpinner::invoke() - { - if (onValueChanged) { - onValueChanged(getCurrentValue()); - } - } - template bool GenericSpinner::isSingle() const - { - return policy.isSingle(); - } - template bool GenericSpinner::isAtMin() const - { - return policy.isAtMin(); - } - template bool GenericSpinner::isAtMax() const - { - return policy.isAtMax(); - } -} // namespace gui diff --git a/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp b/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp index 8a05721080513f5952e8aae69c766acf6cd4df77..e368e1dcf827c52fdc2dc1f84ae8a04fd545b4fc 100644 --- a/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp +++ b/module-apps/apps-common/widgets/spinners/ItemSpinner.hpp @@ -3,27 +3,27 @@ #pragma once -#include "SpinnerPolicies.hpp" #include +#include namespace gui { - template class ItemSpinner : public Item + template class ItemSpinner : public Item { public: - using Range = typename Policy::Range; - using Type = typename Policy::Type; + using range = typename Container::range; + using value_type = typename Container::value_type; - using OnValueChanged = std::function; + using OnValueChanged = std::function; explicit ItemSpinner(Item *parent, - Range range, + range range, Boundaries boundaries = Boundaries::Continuous, Orientation orientation = Orientation::Vertical); - [[nodiscard]] Type getCurrentValue() const noexcept; - void setCurrentValue(Type val); - void setRange(Range range); + [[nodiscard]] value_type getCurrentValue() const noexcept; + void setCurrentValue(value_type val); + void setRange(range range); void setFocusEdges(RectangleEdge edges); bool onInput(const InputEvent &inputEvent) override; @@ -33,6 +33,16 @@ namespace gui OnValueChanged onValueChanged; private: + inline typename Container::Boundaries convert_boundaries(gui::Boundaries boundaries) + { + switch (boundaries) { + case gui::Boundaries::Fixed: + return Container::Boundaries::Fixed; + case gui::Boundaries::Continuous: + return Container::Boundaries::Continuous; + } + return Container::Boundaries::Fixed; + } void stepNext(); void stepPrevious(); bool isPreviousEvent(const InputEvent &inputEvent); @@ -40,18 +50,18 @@ namespace gui void update(); void invoke(); - Policy policy; + Container container; RectangleEdge focusEdges = RectangleEdge::Bottom; Orientation orientation = Orientation::Vertical; gui::Item *currentLayout = nullptr; }; - template - ItemSpinner::ItemSpinner(Item *parent, - ItemSpinner::Range range, - Boundaries boundaries, - Orientation orientation) - : Item(), policy{range, boundaries}, orientation(orientation) + template + ItemSpinner::ItemSpinner(Item *parent, + ItemSpinner::range range, + Boundaries boundaries, + Orientation orientation) + : Item(), container{range, convert_boundaries(boundaries)}, orientation(orientation) { this->parent = parent; if (parent != nullptr) { @@ -59,41 +69,42 @@ namespace gui } } - template void ItemSpinner::setFocusEdges(RectangleEdge edges) + template void ItemSpinner::setFocusEdges(RectangleEdge edges) { focusEdges = edges; } - template void ItemSpinner::setRange(Range range) + template void ItemSpinner::setRange(range range) { - policy.updateRange(range); + container.updateRange(range); update(); } - template void ItemSpinner::setCurrentValue(const Type val) + template void ItemSpinner::setCurrentValue(const value_type val) { - policy.set(val); + container.set(val); update(); } - template typename ItemSpinner::Type ItemSpinner::getCurrentValue() const noexcept + template + typename ItemSpinner::value_type ItemSpinner::getCurrentValue() const noexcept { - return policy.get(); + return container.get(); } - template bool ItemSpinner::isPreviousEvent(const InputEvent &inputEvent) + template bool ItemSpinner::isPreviousEvent(const InputEvent &inputEvent) { return (orientation == Orientation::Vertical && inputEvent.is(KeyCode::KEY_DOWN)) || (orientation == Orientation::Horizontal && inputEvent.is(KeyCode::KEY_LEFT)); } - template bool ItemSpinner::isNextEvent(const InputEvent &inputEvent) + template bool ItemSpinner::isNextEvent(const InputEvent &inputEvent) { return (orientation == Orientation::Vertical && inputEvent.is(KeyCode::KEY_UP)) || (orientation == Orientation::Horizontal && inputEvent.is(KeyCode::KEY_RIGHT)); } - template bool ItemSpinner::onInput(const InputEvent &inputEvent) + template bool ItemSpinner::onInput(const InputEvent &inputEvent) { if (inputEvent.isShortRelease()) { if (isPreviousEvent(inputEvent)) { @@ -108,43 +119,43 @@ namespace gui return false; } - template void ItemSpinner::stepNext() + template void ItemSpinner::stepNext() { - if (policy.next()) { + if (container.next()) { update(); invoke(); } } - template void ItemSpinner::stepPrevious() + template void ItemSpinner::stepPrevious() { - if (policy.previous()) { + if (container.previous()) { update(); invoke(); } } - template void ItemSpinner::update() + template void ItemSpinner::update() { - if (currentLayout) { + if (currentLayout != nullptr) { this->removeWidget(currentLayout); } - currentLayout = policy.get(); + currentLayout = container.get(); this->addWidget(currentLayout); informContentChanged(); } - template void ItemSpinner::invoke() + template void ItemSpinner::invoke() { if (onValueChanged) { onValueChanged(getCurrentValue()); } } - template bool ItemSpinner::isAtMin() const + template bool ItemSpinner::isAtMin() const { - return policy.isAtMin(); + return container.is_min(); } - template bool ItemSpinner::isAtMax() const + template bool ItemSpinner::isAtMax() const { - return policy.isAtMax(); + return container.is_max(); } } // namespace gui diff --git a/module-apps/apps-common/widgets/spinners/Model.hpp b/module-apps/apps-common/widgets/spinners/Model.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b8538afefa1085b9463cb20a8ed42cb7a0308716 --- /dev/null +++ b/module-apps/apps-common/widgets/spinners/Model.hpp @@ -0,0 +1,212 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include +#include + +/// Generic elements container. +/// By default, the container will choose the most optimal way of elements storage. +/// Fundamental types(ints, float, doubles, chars) are stored as simple variables. Compound types are stored in +/// std::vector. +/// Sometimes it is necessary to force the latter way of storing values even for fundamental types. For +/// instance, the user might want to store a fixed list of integers to iterate. In that case, set the force parameter to +/// true. +template class Model +{ + public: + enum class Boundaries + { + Fixed, /// Stop scrolling upon reaching last/first element + Continuous /// Jump to beginning/end upon reaching last/first element + }; + using range = std::vector; + using value_type = ElementType; + + Model(range &&r, Boundaries boundaries) : elements{std::move(r)}, it{elements.begin()}, boundaries{boundaries} + {} + + Model(const range &r, Boundaries boundaries) : elements{r}, it{elements.begin()}, boundaries{boundaries} + {} + + ElementType get() const + { + return it == elements.end() ? ElementType{} : *it; + } + + void set(ElementType val) + { + const auto e = std::find_if(elements.begin(), elements.end(), [&val](const auto &i) { return i == val; }); + if (e != elements.end()) { + it = e; + } + } + + bool next() + { + bool ret{true}; + if (std::next(it) == elements.end()) { + if (boundaries == Boundaries::Continuous) { + it = elements.begin(); + } + else { + ret = false; + } + } + else { + it = std::next(it); + } + return ret; + } + + bool previous() + { + bool ret{true}; + if (it == elements.begin()) { + if (boundaries == Boundaries::Continuous) { + it = std::prev(elements.end()); + } + else { + ret = false; + } + } + else { + it = std::prev(it); + } + return ret; + } + + void set_range(range newRange) + { + if (elements != newRange) { + elements = newRange; + it = elements.begin(); + } + } + + [[nodiscard]] size_t size() const + { + return elements.size(); + } + + [[nodiscard]] bool is_min() const + { + return it == elements.begin(); + } + + [[nodiscard]] bool is_max() const + { + return std::next(it) == elements.end(); + } + + private: + range elements; + typename range::iterator it = elements.end(); + const Boundaries boundaries{}; +}; + +template +class Model and not force>> +{ + struct details + { + struct range + { + ElementType min{}; + ElementType max{}; + ElementType step{}; + + bool operator!=(const range &oth) const + { + return min != oth.min || max != oth.max || step != oth.step; + } + }; + }; + + public: + enum class Boundaries + { + Fixed, + Continuous + }; + using range = typename details::range; + using value_type = ElementType; + + Model(range &&elements, Boundaries boundaries) + : elements{std::move(elements)}, value{elements.min}, boundaries{boundaries} + {} + + Model(range &elements, Boundaries boundaries) : elements{elements}, value{elements.min}, boundaries{boundaries} + {} + + ElementType get() const + { + return value; + } + + void set(ElementType val) + { + value = val; + } + + bool next() + { + bool ret{true}; + if (value >= elements.max) { + if (boundaries == Boundaries::Continuous) { + value = elements.min; + } + else { + value = elements.max; + ret = false; + } + } + else { + value += elements.step; + } + return ret; + } + + bool previous() + { + bool ret{true}; + if (value <= elements.min) { + if (boundaries == Boundaries::Continuous) { + value = elements.max; + } + else { + value = elements.min; + ret = false; + } + } + else { + value -= elements.step; + } + return ret; + } + + void set_range(range newRange) + { + if (elements != newRange) { + elements = newRange; + value = elements.min; + } + } + + [[nodiscard]] bool is_min() const + { + return value == elements.min; + } + + [[nodiscard]] bool is_max() const + { + return value == elements.max; + } + + private: + range elements; + ElementType value{}; + const Boundaries boundaries{}; +}; diff --git a/module-apps/apps-common/widgets/spinners/SpinnerContents.hpp b/module-apps/apps-common/widgets/spinners/SpinnerContents.hpp deleted file mode 100644 index c35d72dafacdd3c4d7c2d97022f00f954444e819..0000000000000000000000000000000000000000 --- a/module-apps/apps-common/widgets/spinners/SpinnerContents.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include - -namespace gui -{ - template class NumWithString - { - public: - NumWithString() = default; - - NumWithString(ValueT value, StringT string) : value{value}, string{string} - {} - - explicit NumWithString(StringT string) : string{string} - {} - explicit NumWithString(ValueT value) : value{value} - {} - - bool operator==(const NumWithString &oth) const - { - return oth.toStr() == toStr(); - } - - operator StringT() const - { - return toStr(); - } - - std::optional getValue() const - { - return value; - } - - std::optional getSuffix() const - { - return string; - } - - private: - StringT toStr() const - { - StringT retStr; - if (value) { - retStr += std::to_string(*value) + " "; - } - if (string) { - retStr += *string; - } - return retStr; - } - std::optional value; - std::optional string; - }; -} // namespace gui diff --git a/module-apps/apps-common/widgets/spinners/SpinnerPolicies.hpp b/module-apps/apps-common/widgets/spinners/SpinnerPolicies.hpp deleted file mode 100644 index 3f50f4e4c6cb22806bfbf3cebf186669c2bb9b9b..0000000000000000000000000000000000000000 --- a/module-apps/apps-common/widgets/spinners/SpinnerPolicies.hpp +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include - -#include -#include -#include -#include - -namespace gui -{ - template class StringPolicy - { - public: - using Range = std::vector; - using Type = ValType; - - StringPolicy(Range range, Boundaries boundaries) : range{range}, boundaries{boundaries} - {} - - ValType get() const - { - return pos < range.size() ? range[pos] : ValType{}; - } - - UTF8 str() const - { - return pos < range.size() ? range[pos] : UTF8{}; - } - - void set(ValType val) - { - for (auto i = 0U; i < range.size(); i++) { - if (range[i] == val) { - pos = i; - break; - } - } - } - - bool next() - { - bool ret{true}; - if (pos >= upRange()) { - if (boundaries == Boundaries::Continuous) { - pos = 0; - } - else { - pos = upRange(); - ret = false; - } - } - else { - pos++; - } - return ret; - } - - bool previous() - { - bool ret{true}; - if (pos <= 0) { - if (boundaries == Boundaries::Continuous) { - pos = upRange(); - } - else { - pos = 0; - ret = false; - } - } - else { - pos--; - } - return ret; - } - - void updateRange(Range newRange) - { - if (range != newRange) { - range = newRange; - pos = 0; - } - } - - [[nodiscard]] bool isSingle() const - { - return range.size() == 1; - } - [[nodiscard]] bool isAtMin() const - { - return pos == 0; - } - [[nodiscard]] bool isAtMax() const - { - return pos == upRange(); - } - - private: - std::uint32_t upRange() const - { - return range.size() - 1; - } - - Range range; - std::uint32_t pos{}; - const Boundaries boundaries{}; - }; - - template class WidgetPolicy - { - public: - using Range = std::vector; - using Type = ValType; - - WidgetPolicy(Range range, Boundaries boundaries) : range{range}, boundaries{boundaries} - {} - - ValType get() const - { - return pos < range.size() ? range[pos] : ValType{}; - } - - void set(ValType val) - { - for (auto i = 0U; i < range.size(); i++) { - if (range[i] == val) { - pos = i; - break; - } - } - } - - bool next() - { - bool ret{true}; - if (pos >= upRange()) { - if (boundaries == Boundaries::Continuous) { - pos = 0; - } - else { - pos = upRange(); - ret = false; - } - } - else { - pos++; - } - return ret; - } - - bool previous() - { - bool ret{true}; - if (pos <= 0) { - if (boundaries == Boundaries::Continuous) { - pos = upRange(); - } - else { - pos = 0; - ret = false; - } - } - else { - pos--; - } - return ret; - } - - void updateRange(Range newRange) - { - if (range != newRange) { - range = newRange; - pos = 0; - } - } - - [[nodiscard]] bool isAtMin() const - { - return pos == 0; - } - [[nodiscard]] bool isAtMax() const - { - return pos == upRange(); - } - - private: - std::uint32_t upRange() const - { - return range.size() - 1; - } - - Range range; - std::uint32_t pos{}; - const Boundaries boundaries{}; - }; - - template class DefaultNumericFormatter - { - public: - std::string operator()(const ValType val) const - { - return std::to_string(val); - } - }; - - template class FixedSizeFormatter - { - public: - std::string operator()(const ValType val) const - { - std::stringstream outStream; - outStream << std::setw(Width) << std::setfill('0') << val; - return outStream.str(); - } - }; - - template > class NumericPolicy - { - struct RangeImpl - { - ValType min; - ValType max; - ValType step; - bool operator!=(const RangeImpl &oth) const - { - return min != oth.min || max != oth.max || step != oth.step; - } - }; - - public: - using Range = RangeImpl; - using Type = ValType; - - NumericPolicy(Range range, Boundaries boundaries) : range{range}, boundaries{boundaries} - {} - - ValType get() const - { - return currentValue; - } - - UTF8 str() const - { - return Formatter{}(currentValue); - } - - void set(ValType val) - { - currentValue = val; - } - - bool next() - { - bool ret{true}; - if (currentValue >= range.max) { - if (boundaries == Boundaries::Continuous) { - currentValue = range.min; - } - else { - currentValue = range.max; - ret = false; - } - } - else { - currentValue += range.step; - } - return ret; - } - - bool previous() - { - bool ret{true}; - if (currentValue <= range.min) { - if (boundaries == Boundaries::Continuous) { - currentValue = range.max; - } - else { - currentValue = range.min; - ret = false; - } - } - else { - currentValue -= range.step; - } - return ret; - } - - void updateRange(Range newRange) - { - if (range != newRange) { - range = newRange; - currentValue = 0; - } - } - - [[nodiscard]] bool isAtMin() const - { - return currentValue == range.min; - } - [[nodiscard]] bool isAtMax() const - { - return currentValue == range.max; - } - - private: - Range range; - ValType currentValue{}; - const Boundaries boundaries{}; - }; - - template class ModelDelegatePolicy - { - public: - using Range = std::vector; - using Type = ValType; - - ModelDelegatePolicy(Range range, Boundaries boundaries) : range{range}, boundaries{boundaries} - {} - - Type get() const - { - return pos < range.size() ? range[pos] : Type{}; - } - - UTF8 str() const - { - return pos < range.size() ? RepresentationType{range[pos]} : RepresentationType{}; - } - - void set(ValType val) - { - for (auto i = 0U; i < range.size(); i++) { - if (range[i] == val) { - pos = i; - break; - } - } - } - - bool next() - { - bool ret{true}; - if (pos >= upRange()) { - if (boundaries == Boundaries::Continuous) { - pos = 0; - } - else { - pos = upRange(); - ret = false; - } - } - else { - pos++; - } - return ret; - } - - bool previous() - { - bool ret{true}; - if (pos <= 0) { - if (boundaries == Boundaries::Continuous) { - pos = upRange(); - } - else { - pos = 0; - ret = false; - } - } - else { - pos--; - } - return ret; - } - - void updateRange(Range newRange) - { - if (range != newRange) { - range = newRange; - pos = 0; - } - } - [[nodiscard]] bool isSingle() const - { - return range.size() == 1; - } - [[nodiscard]] bool isAtMin() const - { - return pos == 0; - } - [[nodiscard]] bool isAtMax() const - { - return pos == upRange(); - } - - private: - std::uint32_t upRange() const - { - return range.size() - 1; - } - - Range range; - std::uint32_t pos{}; - const Boundaries boundaries{}; - }; - -} // namespace gui diff --git a/module-apps/apps-common/widgets/spinners/Spinners.hpp b/module-apps/apps-common/widgets/spinners/Spinners.hpp index 383632a0e3366e858c25af1b62e62ec4a792969f..568f163ffbe67c947fc1893189e89dea8be0a941 100644 --- a/module-apps/apps-common/widgets/spinners/Spinners.hpp +++ b/module-apps/apps-common/widgets/spinners/Spinners.hpp @@ -3,16 +3,31 @@ #pragma once -#include "GenericSpinner.hpp" +#include "ItemSpinner.hpp" + +#include "Model.hpp" +#include "StringOutputSpinner.hpp" #include "ItemSpinner.hpp" namespace gui { - using UTF8Spinner = GenericSpinner>; - using UIntegerSpinner = GenericSpinner>; - using UIntegerSpinnerFixed = GenericSpinner>>; - using IntegerSpinner = GenericSpinner>; - using WidgetSpinner = ItemSpinner>; + template struct FixedIntegerFormatter + { + std::string operator()(const ValType val) const + { + std::stringstream outStream; + outStream << std::setw(Width) << std::setfill('0') << val; + return outStream.str(); + } + }; + + using StringContainer = Model; + using UINT8Container = Model; + + using StringSpinner = StringOutputSpinner; + using UIntegerSpinner = StringOutputSpinner; + using UIntegerSpinnerFixed = StringOutputSpinner>; + using WidgetSpinner = ItemSpinner>; + template using UIntegerSpinnerWithFormatter = StringOutputSpinner; - template using ModelDelegateSpinner = GenericSpinner>; } // namespace gui diff --git a/module-apps/apps-common/widgets/spinners/StringOutputSpinner.hpp b/module-apps/apps-common/widgets/spinners/StringOutputSpinner.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bb357ed9c8140b429b7109e39ee6bc21beab7e8a --- /dev/null +++ b/module-apps/apps-common/widgets/spinners/StringOutputSpinner.hpp @@ -0,0 +1,237 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include +#include + +namespace details +{ + template struct container_data + { + using value = T; + }; + + template struct container_data>> + { + using value = typename T::value_type; + }; + + template using container_data_v = typename container_data::value; + +} // namespace details + +namespace gui +{ + // This spinner operates on container elements and transforms the current container into a string. + // For the containers of types that are convertible to strings like std::string, integer, floating-point integers, + // there is no need to provide the custom formatter. However, it is possible to pass a formatter if a user wants to + // perform custom formatting. It is not possible to use a formatter when using container of std::string. + template class StringOutputSpinner : public TextFixedSize + { + public: + using range = typename Container::range; + using value_type = details::container_data_v; + + explicit StringOutputSpinner(Container &&container, Orientation orientation = Orientation::Vertical) + : container{std::move(container)}, orientation{orientation} + { + init(); + } + + explicit StringOutputSpinner(range &range, + Boundaries boundaries = Boundaries::Fixed, + Orientation orientation = Orientation::Vertical) + : container{range, convert_boundaries(boundaries)}, orientation{orientation} + { + init(); + } + + explicit StringOutputSpinner(range &&range, + Boundaries boundaries = Boundaries::Fixed, + Orientation orientation = Orientation::Vertical) + : container{std::move(range), convert_boundaries(boundaries)}, orientation{orientation} + { + init(); + } + + using OnValueChanged = std::function; + void setFocusEdges(RectangleEdge edges); + bool onInput(const InputEvent &inputEvent) override; + bool onFocus(bool state) override; + [[nodiscard]] size_t size() const; + [[nodiscard]] bool is_min() const; + [[nodiscard]] bool is_max() const; + + OnValueChanged onValueChanged; + + void set_range(const range &range); + void set_value(const value_type &value); + [[nodiscard]] auto value() const noexcept; + + private: + inline typename Container::Boundaries convert_boundaries(gui::Boundaries boundaries) + { + switch (boundaries) { + case gui::Boundaries::Fixed: + return Container::Boundaries::Fixed; + case gui::Boundaries::Continuous: + return Container::Boundaries::Continuous; + } + return Container::Boundaries::Fixed; + } + void init(); + [[nodiscard]] std::string value_as_str() const noexcept; + void next(); + void previous(); + bool is_previous_event(const InputEvent &inputEvent); + bool is_next_event(const InputEvent &inputEvent); + void update(); + void invoke(); + + static constexpr bool is_string = + std::is_same_v or std::is_convertible_v; + static constexpr bool is_fundamental = std::is_fundamental_v; + static constexpr bool is_formatter_defined = not std::is_same_v; + + Container container; + RectangleEdge focusEdges = RectangleEdge::Bottom; + Orientation orientation = Orientation::Vertical; + }; + + template + auto StringOutputSpinner::value() const noexcept + { + return container.get(); + } + + template + std::string StringOutputSpinner::value_as_str() const noexcept + { + if constexpr (is_string) { + return container.get(); + } + else if constexpr (is_fundamental and not is_formatter_defined) { + return std::to_string(container.get()); + } + else { + return Formatter{}(container.get()); + } + } + + template + void StringOutputSpinner::setFocusEdges(RectangleEdge edges) + { + focusEdges = edges; + } + + template + bool StringOutputSpinner::onInput(const InputEvent &inputEvent) + { + if (inputEvent.isShortRelease()) { + if (is_previous_event(inputEvent)) { + previous(); + return true; + } + else if (is_next_event(inputEvent)) { + next(); + return true; + } + } + return false; + } + + template + bool StringOutputSpinner::onFocus(bool state) + { + if (focus) { + setEdges(focusEdges); + } + else { + setEdges(RectangleEdge::None); + } + showCursor(state); + return true; + } + + template size_t StringOutputSpinner::size() const + { + return container.size(); + } + + template bool StringOutputSpinner::is_min() const + { + return container.is_min(); + } + + template bool StringOutputSpinner::is_max() const + { + return container.is_max(); + } + + template + void StringOutputSpinner::set_value(const value_type &value) + { + container.set(value); + update(); + } + + template + void StringOutputSpinner::set_range(const range &range) + { + container.set_range(range); + update(); + } + + template void StringOutputSpinner::next() + { + if (container.next()) { + update(); + invoke(); + } + } + + template void StringOutputSpinner::previous() + { + if (container.previous()) { + update(); + invoke(); + } + } + template void StringOutputSpinner::update() + { + setText(value_as_str()); + } + + template void StringOutputSpinner::invoke() + { + if (onValueChanged) { + onValueChanged(value()); + } + } + + template + bool StringOutputSpinner::is_previous_event(const InputEvent &inputEvent) + { + return (orientation == Orientation::Vertical && inputEvent.is(KeyCode::KEY_DOWN)) || + (orientation == Orientation::Horizontal && inputEvent.is(KeyCode::KEY_LEFT)); + } + + template + bool StringOutputSpinner::is_next_event(const InputEvent &inputEvent) + { + return (orientation == Orientation::Vertical && inputEvent.is(KeyCode::KEY_UP)) || + (orientation == Orientation::Horizontal && inputEvent.is(KeyCode::KEY_RIGHT)); + } + + template void StringOutputSpinner::init() + { + setEditMode(EditMode::Browse); + drawUnderline(false); + update(); + } + +} // namespace gui diff --git a/module-apps/tests/CMakeLists.txt b/module-apps/tests/CMakeLists.txt index 7c32e721d396b753fcf165640fb2bf357bb85d60..6d2e7c9b36e16b8a17fd56b9bd5d648ae0870555 100644 --- a/module-apps/tests/CMakeLists.txt +++ b/module-apps/tests/CMakeLists.txt @@ -5,6 +5,7 @@ add_catch2_executable( test-CallbackStorage.cpp test-PhoneModesPolicies.cpp tests-BluetoothSettingsModel.cpp + test-Model.cpp LIBS module-apps ) diff --git a/module-apps/tests/test-Model.cpp b/module-apps/tests/test-Model.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bcccd1b9404b1a4ba54d81f7b7b224e16c01f34 --- /dev/null +++ b/module-apps/tests/test-Model.cpp @@ -0,0 +1,199 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +#include + +TEST_CASE("Model") +{ + SECTION("Empty") + { + using UINT8Model = Model; + + auto container = UINT8Model{{}, UINT8Model::Boundaries::Fixed}; + + REQUIRE(container.get() == 0); + } + + SECTION("Force underlying structure") + { + using ForcedContainer = Model; + + auto container = ForcedContainer{{5, 10, 2, 30, 25}, ForcedContainer::Boundaries::Fixed}; + + REQUIRE(container.get() == 5); + container.set(25); + REQUIRE(container.get() == 25); + container.set(2); + REQUIRE(container.get() == 2); + } + + SECTION("Fundamental types") + { + using UINT8Model = Model; + auto range = UINT8Model::range{0, 10, 1}; + const auto boundaries = UINT8Model::Boundaries::Fixed; + SECTION("set") + { + auto container = UINT8Model{range, boundaries}; + + REQUIRE(container.get() == 0); + container.set(5); + REQUIRE(container.get() == 5); + } + + SECTION("check step") + { + auto container = UINT8Model{UINT8Model::range{0, 6, 3}, boundaries}; + + REQUIRE(container.get() == 0); + container.next(); + REQUIRE(container.get() == 3); + container.previous(); + REQUIRE(container.get() == 0); + } + + SECTION("Check boundaries") + { + SECTION("Fixed") + { + auto container = UINT8Model{range, boundaries}; + + REQUIRE(container.get() == 0); + container.previous(); + REQUIRE(container.get() == 0); + + container.set(10); + REQUIRE(container.get() == 10); + container.next(); + REQUIRE(container.get() == 10); + } + + SECTION("Continuous") + { + auto container = UINT8Model{range, UINT8Model::Boundaries::Continuous}; + + REQUIRE(container.get() == 0); + container.previous(); + REQUIRE(container.get() == 10); + + container.set(10); + REQUIRE(container.get() == 10); + container.next(); + REQUIRE(container.get() == 0); + } + } + + SECTION("is_min/is_max") + { + auto container = UINT8Model{range, boundaries}; + + REQUIRE(container.is_min()); + REQUIRE_FALSE(container.is_max()); + + container.next(); + REQUIRE_FALSE(container.is_min()); + REQUIRE_FALSE(container.is_max()); + + container.set(10); + REQUIRE_FALSE(container.is_min()); + REQUIRE(container.is_max()); + } + + SECTION("set_range") + { + auto container = UINT8Model{range, boundaries}; + + REQUIRE(container.get() == 0); + + container.set_range(UINT8Model::range{1, 3, 1}); + REQUIRE(container.get() == 1); + } + } + + SECTION("Complex types") + { + using ComplexContainer = Model; + const auto one = "one"; + const auto two = "two"; + const auto three = "three"; + auto range = ComplexContainer::range{one, two, three}; + const auto boundaries = ComplexContainer::Boundaries::Fixed; + SECTION("set") + { + + auto container = ComplexContainer{range, boundaries}; + + REQUIRE(container.get() == one); + container.set(two); + REQUIRE(container.get() == two); + } + + SECTION("check step") + { + auto container = ComplexContainer{range, boundaries}; + + REQUIRE(container.get() == one); + container.next(); + REQUIRE(container.get() == two); + } + + SECTION("Check boundaries") + { + SECTION("Fixed") + { + auto container = ComplexContainer{range, boundaries}; + + REQUIRE(container.get() == one); + container.previous(); + REQUIRE(container.get() == one); + + container.set(three); + REQUIRE(container.get() == three); + container.next(); + REQUIRE(container.get() == three); + } + + SECTION("Continuous") + { + auto container = ComplexContainer{range, ComplexContainer::Boundaries::Continuous}; + + REQUIRE(container.get() == one); + container.previous(); + REQUIRE(container.get() == three); + + container.set(three); + REQUIRE(container.get() == three); + container.next(); + REQUIRE(container.get() == one); + } + } + + SECTION("is_min/is_max") + { + auto container = ComplexContainer{range, boundaries}; + + REQUIRE(container.is_min()); + REQUIRE_FALSE(container.is_max()); + + container.next(); + REQUIRE_FALSE(container.is_min()); + REQUIRE_FALSE(container.is_max()); + + container.set(three); + REQUIRE_FALSE(container.is_min()); + REQUIRE(container.is_max()); + } + + SECTION("set_range") + { + auto container = ComplexContainer{range, boundaries}; + + REQUIRE(container.get() == one); + + container.set_range(ComplexContainer::range{"two", "three", "four"}); + REQUIRE(container.get() == two); + } + } +} diff --git a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp index 0b121f46e4cef6b7fe32235fb3dfd1807b8440a4..a0d118196d4f755d89155c2043b606fdf91540b7 100644 --- a/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp +++ b/module-bsp/board/rt1051/bsp/audio/CodecMAX98090.hpp @@ -8,6 +8,8 @@ #include "drivers/i2c/DriverI2C.hpp" #include +#include + class CodecParamsMAX98090 : public CodecParams { public: @@ -66,8 +68,8 @@ class CodecParamsMAX98090 : public CodecParams bool micBiasEnable = false; std::uint8_t playbackPathGain = 0; std::uint8_t playbackPathAtten = 0; - InputPath inputPath = InputPath::None; - OutputPath outputPath = OutputPath::None; + InputPath inputPath = InputPath::None; + OutputPath outputPath = OutputPath::None; }; class CodecMAX98090 : public Codec diff --git a/products/BellHybrid/BellHybridMain.cpp b/products/BellHybrid/BellHybridMain.cpp index 0320df8211ef079d910343ec911d56ae65a47953..f93addc00f344f50d8a16439c6392bc2f69aabb5 100644 --- a/products/BellHybrid/BellHybridMain.cpp +++ b/products/BellHybrid/BellHybridMain.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -113,8 +113,7 @@ int main() app::CreateLauncher(app::applicationBellOnBoardingName)); applications.push_back( app::CreateLauncher(app::applicationBellBackgroundSoundsName)); - applications.push_back( - app::CreateLauncher(app::applicationBellMeditationTimerName)); + applications.push_back(app::CreateLauncher(app::MeditationTimer::defaultName)); // start application manager return sysmgr->RunSystemService( std::make_shared( diff --git a/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.cpp b/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.cpp index efa681f96d497cb70ac59f07618353c5e673a798..8d7f960d1301dbd0a7922ef4b02706dacc82f9d9 100644 --- a/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.cpp +++ b/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.cpp @@ -86,20 +86,20 @@ namespace gui { auto range = presenter->getTimerValuesRange(); - spinner = new UTF8Spinner(toUTF8Range(range), Boundaries::Fixed); + spinner = new StringSpinner(toUTF8Range(range), Boundaries::Fixed); spinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h); spinner->setFont(bgSoundsStyle::timerValueFont); spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); spinner->setEdges(RectangleEdge::None); spinner->setFocusEdges(RectangleEdge::None); auto currentValue = timerValueToUTF8(presenter->getCurrentTimerValue()); - spinner->setCurrentValue(std::move(currentValue)); + spinner->set_value(std::move(currentValue)); spinner->onValueChanged = [this](const auto &) { - body->setMinMaxArrowsVisibility(spinner->isAtMin(), spinner->isAtMax()); + body->setMinMaxArrowsVisibility(spinner->is_min(), spinner->is_max()); updateBottomDescription(); }; body->getCenterBox()->addWidget(spinner); - body->setMinMaxArrowsVisibility(spinner->isAtMin(), spinner->isAtMax()); + body->setMinMaxArrowsVisibility(spinner->is_min(), spinner->is_max()); } void BGSoundsTimerSelectWindow::createBottomDescription() @@ -117,7 +117,7 @@ namespace gui } void BGSoundsTimerSelectWindow::updateBottomDescription() { - const auto currentVal = spinner->getCurrentValue(); + const auto currentVal = spinner->value(); bottomDescription->setText(utils::language::getCorrectMinutesNumeralForm(UTF8ToTimerValue(currentVal).count())); const bool isDescriptionVisible = UTF8ToTimerValue(currentVal) != offValue; @@ -158,7 +158,7 @@ namespace gui return true; } if (inputEvent.isShortRelease(KeyCode::KEY_ENTER)) { - auto currentValue = UTF8ToTimerValue(spinner->getCurrentValue()); + auto currentValue = UTF8ToTimerValue(spinner->value()); presenter->setTimerValue(currentValue); auto audioSwitchData = std::make_unique(std::move(audioContext)); diff --git a/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.hpp b/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.hpp index 74ec441e724c22891cec135fd1d4606cb76eabec..7a3e6518be4badc7912725fd4eab106ca656e8e1 100644 --- a/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.hpp +++ b/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsTimerSelectWindow.hpp @@ -18,7 +18,7 @@ namespace gui { std::unique_ptr presenter; BellBaseLayout *body = nullptr; - UTF8Spinner *spinner = nullptr; + StringSpinner *spinner = nullptr; Text *bottomDescription = nullptr; std::unique_ptr audioContext; diff --git a/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.cpp b/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.cpp index 10fa935c0c6259470a5005e425f3e6cfb612df81..c7ac702ef31cfb45caf3b2a8f5608354fb774d42 100644 --- a/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.cpp +++ b/products/BellHybrid/apps/application-bell-background-sounds/windows/BGSoundsVolumeWindow.cpp @@ -36,19 +36,19 @@ namespace gui topMessage->drawUnderline(false); auto data = presenter->getVolumeData(); - spinner = new UIntegerSpinner({static_cast(data.min), - static_cast(data.max), - static_cast(data.step)}, + spinner = new UIntegerSpinner({static_cast(data.min), + static_cast(data.max), + static_cast(data.step)}, Boundaries::Fixed); spinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::center_layout_h); spinner->setFont(bgSoundsStyle::valumeValueFont); spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); spinner->setFocusEdges(RectangleEdge::None); - spinner->setCurrentValue(static_cast(presenter->getVolume())); + spinner->set_value(static_cast(presenter->getVolume())); body->getCenterBox()->addWidget(spinner); spinner->onValueChanged = [this](const auto &value) { presenter->setVolume(value); }; - body->setMinMaxArrowsVisibility(spinner->getCurrentValue() == data.min, spinner->getCurrentValue() == data.max); + body->setMinMaxArrowsVisibility(spinner->value() == data.min, spinner->value() == data.max); setFocusItem(body); body->resize(); @@ -63,7 +63,7 @@ namespace gui resetTimer(); auto data = presenter->getVolumeData(); const auto ret = body->onInput(inputEvent); - const auto selectedVal = spinner->getCurrentValue(); + const auto selectedVal = spinner->value(); body->setMinMaxArrowsVisibility(selectedVal == data.min, selectedVal == data.max); return ret; } diff --git a/products/BellHybrid/apps/application-bell-main/windows/BellMainMenuWindow.cpp b/products/BellHybrid/apps/application-bell-main/windows/BellMainMenuWindow.cpp index 961e8b55519eaea5cc2de0c8e64aef99c127031b..cab33eec24380f79495739b03ee9629ef5c7b50e 100644 --- a/products/BellHybrid/apps/application-bell-main/windows/BellMainMenuWindow.cpp +++ b/products/BellHybrid/apps/application-bell-main/windows/BellMainMenuWindow.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -49,7 +49,7 @@ namespace gui addAppMenu(utils::translate("app_bellmain_alarm"), app::applicationBellAlarmName); addAppMenu(utils::translate("app_bellmain_power_nap"), app::applicationBellPowerNapName); addAppMenu(utils::translate("app_bellmain_background_sounds"), app::applicationBellBackgroundSoundsName); - addAppMenu(utils::translate("app_bellmain_meditation_timer"), app::applicationBellMeditationTimerName); + addAppMenu(utils::translate("app_bellmain_meditation_timer"), app::MeditationTimer::defaultName); addAppMenu(utils::translate("app_bellmain_bedtime"), app::applicationBellBedtimeName); addAppMenu(utils::translate("app_bellmain_settings"), app::applicationBellSettingsName); diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/ApplicationBellMeditationTimer.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/ApplicationBellMeditationTimer.cpp deleted file mode 100644 index abd32ca5c75bb5675d30e8a6ca2e709f7657d6c0..0000000000000000000000000000000000000000 --- a/products/BellHybrid/apps/application-bell-meditation-timer/ApplicationBellMeditationTimer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "ApplicationBellMeditationTimer.hpp" -#include "windows/IntervalChimeWindow.hpp" -#include "windows/MeditationRunningWindow.hpp" -#include "windows/MeditationTimerWindow.hpp" -#include "windows/ReadyGoingWindow.hpp" - -#include -#include -#include - -namespace app -{ - ApplicationBellMeditationTimer::ApplicationBellMeditationTimer(std::string name, - std::string parent, - StatusIndicators statusIndicators, - StartInBackground startInBackground, - uint32_t stackDepth) - : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth) - {} - - ApplicationBellMeditationTimer::~ApplicationBellMeditationTimer() = default; - - sys::ReturnCodes ApplicationBellMeditationTimer::InitHandler() - { - auto ret = Application::InitHandler(); - if (ret != sys::ReturnCodes::Success) { - return ret; - } - - createUserInterface(); - - return sys::ReturnCodes::Success; - } - - void ApplicationBellMeditationTimer::createUserInterface() - { - windowsFactory.attach(gui::name::window::main_window, [this](ApplicationCommon *app, const std::string &name) { - auto presenter = std::make_unique(app, settings.get()); - return std::make_unique(app, std::move(presenter)); - }); - windowsFactory.attach( - gui::name::window::intervalChime, [this](ApplicationCommon *app, const std::string &name) { - auto presenter = std::make_unique(app, settings.get()); - return std::make_unique(app, std::move(presenter)); - }); - windowsFactory.attach(gui::name::window::readyGoing, [](ApplicationCommon *app, const std::string &name) { - auto presenter = std::make_unique(app); - return std::make_unique(app, std::move(presenter)); - }); - windowsFactory.attach(gui::name::window::meditationProgress, - [this](ApplicationCommon *app, const std::string &name) { - auto timeModel = std::make_unique(); - auto presenter = std::make_unique( - app, settings.get(), std::move(timeModel)); - return std::make_unique(app, std::move(presenter)); - }); - windowsFactory.attach(gui::window::session_paused::sessionPaused, - [](ApplicationCommon *app, const std::string &name) { - return std::make_unique(app); - }); - windowsFactory.attach(gui::window::bell_finished::defaultName, - [](ApplicationCommon *app, const std::string &name) { - return std::make_unique(app, name); - }); - - attachPopups({gui::popup::ID::AlarmActivated, - gui::popup::ID::AlarmDeactivated, - gui::popup::ID::PowerOff, - gui::popup::ID::Reboot, - gui::popup::ID::BedtimeNotification}); - } - - sys::MessagePointer ApplicationBellMeditationTimer::DataReceivedHandler(sys::DataMessage *msgl, - sys::ResponseMessage *resp) - { - auto retMsg = Application::DataReceivedHandler(msgl); - if (auto response = dynamic_cast(retMsg.get()); - response != nullptr && response->retCode == sys::ReturnCodes::Success) { - return retMsg; - } - - return handleAsyncResponse(resp); - } -} // namespace app diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt b/products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt index 27009ad6ce128747aa2b6d5e413798779c226df4..df78fdd0f42d7fd66838dca6234083fe68cd3760 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt +++ b/products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt @@ -18,18 +18,24 @@ target_include_directories(application-bell-meditation-timer target_sources(application-bell-meditation-timer PRIVATE - ApplicationBellMeditationTimer.cpp - presenter/IntervalChimePresenter.cpp + MeditationTimer.cpp + models/ChimeInterval.cpp + models/ChimeVolume.cpp + models/StartDelay.cpp presenter/MeditationProgressPresenter.cpp presenter/MeditationTimerPresenter.cpp presenter/ReadyGoingPresenter.cpp - presenter/SessionEndedPresenter.cpp - windows/IntervalChimeWindow.cpp + presenter/SessionEndedPresenter.cpp + presenter/SettingsPresenter.cpp + presenter/StatisticsPresenter.cpp + windows/MeditationMainWindow.cpp windows/MeditationRunningWindow.cpp windows/MeditationTimerWindow.cpp windows/ReadyGoingWindow.cpp + windows/SettingsWindow.cpp + windows/StatisticsWindow.cpp PUBLIC - include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp + include/application-bell-meditation-timer/MeditationTimer.hpp ) target_link_libraries(application-bell-meditation-timer @@ -38,7 +44,6 @@ target_link_libraries(application-bell-meditation-timer bell::audio bell::app-common bell::app-main - bellgui service-appmgr service-time PUBLIC diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ee44099e1238271a9126f07835c8e4447c6b339 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp @@ -0,0 +1,114 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "MeditationTimer.hpp" +#include "MeditationCommon.hpp" +#include "windows/MeditationMainWindow.hpp" +#include "windows/MeditationRunningWindow.hpp" +#include "windows/MeditationTimerWindow.hpp" +#include "windows/ReadyGoingWindow.hpp" +#include "windows/SettingsWindow.hpp" +#include "windows/StatisticsWindow.hpp" + +#include "models/ChimeVolume.hpp" +#include "models/StartDelay.hpp" +#include "models/ChimeInterval.hpp" + +#include "presenter/SettingsPresenter.hpp" +#include "presenter/StatisticsPresenter.hpp" + +#include +#include +#include + +namespace app +{ + MeditationTimer::MeditationTimer(std::string name, + std::string parent, + StatusIndicators statusIndicators, + StartInBackground startInBackground, + uint32_t stackDepth) + : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, stackDepth) + {} + + sys::ReturnCodes MeditationTimer::InitHandler() + { + auto ret = Application::InitHandler(); + if (ret != sys::ReturnCodes::Success) { + return ret; + } + + chimeIntervalModel = std::make_unique(this); + chimeVolumeModel = std::make_unique(this); + startDelayModel = std::make_unique(this); + + createUserInterface(); + + return sys::ReturnCodes::Success; + } + + void MeditationTimer::createUserInterface() + { + windowsFactory.attach( + meditation::MeditationMainWindow::defaultName, [this](ApplicationCommon *app, const std::string &name) { + auto presenter = std::make_unique(app, settings.get()); + return std::make_unique(app); + }); + + windowsFactory.attach(meditation::SettingsWindow::name, + [this](ApplicationCommon *app, const std::string &name) { + auto presenter = std::make_unique( + app, *chimeIntervalModel, *chimeVolumeModel, *startDelayModel); + return std::make_unique(app, std::move(presenter)); + }); + + windowsFactory.attach(meditation::StatisticsWindow::name, [](ApplicationCommon *app, const std::string &name) { + auto presenter = std::make_unique(); + return std::make_unique(app, std::move(presenter)); + }); + + windowsFactory.attach( + meditation::MeditationTimerWindow::name, [this](ApplicationCommon *app, const std::string &name) { + auto presenter = std::make_unique(app, settings.get()); + return std::make_unique(app, std::move(presenter)); + }); + + windowsFactory.attach(meditation::windows::readyGoing, [this](ApplicationCommon *app, const std::string &name) { + auto presenter = std::make_unique(app, *startDelayModel); + return std::make_unique(app, std::move(presenter)); + }); + windowsFactory.attach(meditation::windows::meditationProgress, + [this](ApplicationCommon *app, const std::string &name) { + auto timeModel = std::make_unique(); + auto presenter = std::make_unique( + app, settings.get(), std::move(timeModel), *chimeIntervalModel); + return std::make_unique(app, std::move(presenter)); + }); + windowsFactory.attach(gui::window::session_paused::sessionPaused, + [](ApplicationCommon *app, const std::string &name) { + return std::make_unique(app); + }); + windowsFactory.attach(gui::window::bell_finished::defaultName, + [](ApplicationCommon *app, const std::string &name) { + return std::make_unique(app, name); + }); + + attachPopups({gui::popup::ID::AlarmActivated, + gui::popup::ID::AlarmDeactivated, + gui::popup::ID::PowerOff, + gui::popup::ID::Reboot, + gui::popup::ID::BedtimeNotification}); + } + + sys::MessagePointer MeditationTimer::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) + { + auto retMsg = Application::DataReceivedHandler(msgl); + if (auto response = dynamic_cast(retMsg.get()); + response != nullptr && response->retCode == sys::ReturnCodes::Success) { + return retMsg; + } + + return handleAsyncResponse(resp); + } + MeditationTimer::~MeditationTimer() = default; +} // namespace app diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a51066d42f936a9f2389cd8e2e27bd23aed75b95 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/data/Contract.hpp @@ -0,0 +1,27 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include + +namespace app::meditation::contract +{ + class View + { + public: + virtual ~View() noexcept = default; + }; + + class Presenter : public BasePresenter + { + public: + virtual ~Presenter() noexcept = default; + virtual auto getPagesProvider() const -> std::shared_ptr = 0; + virtual void loadData() = 0; + virtual void saveData() = 0; + virtual void eraseProviderData() = 0; + virtual void handleEnter() = 0; + }; +} // namespace app::meditation::contract diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp index 83c1fb9912032b691e5b4b2db3a1b3eaab243589..05ba03cb14642cfe066f9f3844e6aa49d80d2af6 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp @@ -5,6 +5,12 @@ namespace app::meditation { + namespace windows + { + static constexpr auto meditationProgress = "MeditationProgress"; + static constexpr auto readyGoing = "MeditationReadyGoing"; + static constexpr auto sessionEnded = "MeditationSessionEnded"; + }; // namespace windows + constexpr auto meditationDBRecordName = "MeditationTimer"; - constexpr auto intervalDBRecordName = "IntervalChime"; } // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp deleted file mode 100644 index 038053e76f2091bbb641fa56667db6018c122554..0000000000000000000000000000000000000000 --- a/products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include - -namespace gui::name::window -{ - inline constexpr auto intervalChime = "IntervalChimeWindow"; - inline constexpr auto meditationProgress = "MeditationProgressWindow"; - inline constexpr auto meditationTimer = "MeditationTimerWindow"; - inline constexpr auto readyGoing = "ReadyGoingWindow"; - inline constexpr auto sessionEnded = "SessionEndedWindow"; -} // namespace gui::name::window - -namespace app -{ - inline constexpr auto applicationBellMeditationTimerName = "ApplicationBellMeditationTimer"; - - class ApplicationBellMeditationTimer : public Application - { - public: - ApplicationBellMeditationTimer(std::string name = applicationBellMeditationTimerName, - std::string parent = "", - StatusIndicators statusIndicators = StatusIndicators{}, - StartInBackground startInBackground = {false}, - uint32_t stackDepth = 4096 * 2); - ~ApplicationBellMeditationTimer(); - - sys::ReturnCodes InitHandler() override; - - void createUserInterface() override; - void destroyUserInterface() override - {} - - sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override; - - sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final - { - return sys::ReturnCodes::Success; - } - }; - - template <> struct ManifestTraits - { - static auto GetManifest() -> manager::ApplicationManifest - { - return {{manager::actions::Launch}}; - } - }; -} // namespace app diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..04004966e79e18df2d726c40602bf96dc8f119d5 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::meditation::models +{ + class ChimeInterval; + class ChimeVolume; + class StartDelay; +} // namespace app::meditation::models + +namespace app +{ + class MeditationTimer : public Application + { + public: + static constexpr auto defaultName = "ApplicationMeditationTimer"; + + explicit MeditationTimer(std::string name = defaultName, + std::string parent = "", + StatusIndicators statusIndicators = StatusIndicators{}, + StartInBackground startInBackground = {false}, + uint32_t stackDepth = 4096 * 2); + ~MeditationTimer(); + + sys::ReturnCodes InitHandler() override; + + void createUserInterface() override; + void destroyUserInterface() override + {} + + sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override; + + sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final + { + return sys::ReturnCodes::Success; + } + + private: + std::unique_ptr chimeIntervalModel; + std::unique_ptr chimeVolumeModel; + std::unique_ptr startDelayModel; + }; + + template <> struct ManifestTraits + { + static auto GetManifest() -> manager::ApplicationManifest + { + return {{manager::actions::Launch}}; + } + }; +} // namespace app diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1b2e1cc72929f212d2f3151425104d486bc1e3f --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.cpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "ChimeInterval.hpp" +#include + +namespace +{ + constexpr auto chime_interval_db = "chime_interval"; + + /// Fraction numbers are stored using "n/d" format. + app::list_items::FractionData to_fraction_data(const std::string &str) + { + const std::string delimiter = "/"; + std::string nominator = str.substr(0, str.find(delimiter)); + std::string denominator = str.substr(str.find(delimiter) + 1); + return {utils::getNumericValue(nominator), utils::getNumericValue(denominator)}; + } + std::string from_fraction_data(const app::list_items::FractionData &data) + { + return std::to_string(data.nominator) + "/" + std::to_string(data.denominator); + } +} // namespace + +namespace app::meditation::models +{ + void ChimeInterval::setValue(app::list_items::FractionData value) + { + settings.setValue(chime_interval_db, from_fraction_data(value)); + } + app::list_items::FractionData ChimeInterval::getValue() const + { + const auto value = settings.getValue(chime_interval_db); + if (value.empty()) { + /// If not found, return 1/1 which corresponds to 'OFF' + return {1, 1}; + } + return to_fraction_data(value); + } +} // namespace app::meditation::models diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eb2c45450a77a0e948392160a6a534dc5c685d64 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeInterval.hpp @@ -0,0 +1,19 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include + +namespace app::meditation::models +{ + class ChimeInterval : public gui::SettingsModel + { + public: + using SettingsModel::SettingsModel; + + void setValue(list_items::FractionData value) override; + list_items::FractionData getValue() const override; + }; +} // namespace app::meditation::models diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be4bfc99db88fd7e2ea9c2faed0b08e51bb92c9b --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.cpp @@ -0,0 +1,18 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "ChimeVolume.hpp" + +namespace app::meditation::models +{ + + void ChimeVolume::setValue(std::uint8_t value) + { + /// Dummy implementation. + } + std::uint8_t ChimeVolume::getValue() const + { + /// Dummy implementation + return 5; + } +} // namespace app::meditation::models diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.hpp new file mode 100644 index 0000000000000000000000000000000000000000..021f38ae08c421379aa332af23dbbd5dc939a2ba --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/models/ChimeVolume.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::meditation::models +{ + class ChimeVolume : public gui::SettingsModel + { + public: + using SettingsModel::SettingsModel; + + void setValue(std::uint8_t value) override; + std::uint8_t getValue() const override; + }; +} // namespace app::meditation::models diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3cbe8f5f543828349eb9d23e9f11855a181da6cb --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "StartDelay.hpp" +#include + +namespace +{ + constexpr auto start_delay_db = "start_delay"; +} // namespace + +namespace app::meditation::models +{ + + void StartDelay::setValue(std::uint8_t value) + { + settings.setValue(start_delay_db, std::to_string(value)); + } + std::uint8_t StartDelay::getValue() const + { + const auto value = settings.getValue(start_delay_db); + if (value.empty()) { + return 0; + } + return utils::getNumericValue(value); + } +} // namespace app::meditation::models diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.hpp new file mode 100644 index 0000000000000000000000000000000000000000..468963e03fad677ac51c88ce60c5a5c25a15d02c --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/models/StartDelay.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::meditation::models +{ + class StartDelay : public gui::SettingsModel + { + public: + using SettingsModel::SettingsModel; + + void setValue(std::uint8_t value) override; + std::uint8_t getValue() const override; + }; +} // namespace app::meditation::models diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp deleted file mode 100644 index e8d8ca04916a86a3bf8582afda6bb3b6119d02af..0000000000000000000000000000000000000000 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "ApplicationBellMeditationTimer.hpp" -#include "IntervalChimePresenter.hpp" -#include "MeditationCommon.hpp" -#include "MeditationStyle.hpp" - -#include - -namespace app::meditation -{ - constexpr auto intervalsList = {1, 2, 5, 10, 15, 30}; - - IntervalChimePresenter::IntervalChimePresenter(app::ApplicationCommon *app, settings::Settings *settings) - : app{app}, settings{settings} - { - initIntervalOptions(); - } - - std::vector IntervalChimePresenter::getIntervals() const - { - std::vector intervalNames; - for (auto const &option : intervalOptions) { - intervalNames.push_back(option.second); - } - return intervalNames; - } - - std::string IntervalChimePresenter::getCurrentInterval() const - { - const auto value = settings->getValue(intervalDBRecordName, settings::SettingsScope::AppLocal); - for (auto const &option : intervalOptions) { - if (utils::to_string(option.first.count()) == value) { - return option.second; - } - } - // If not found, return "None" - return intervalOptions.at(0).second; - } - - std::string IntervalChimePresenter::getTimeUnitName(std::string value) - { - using namespace app::meditationStyle::mtStyle::list; - for (auto const &option : intervalOptions) { - if (option.second == value) { - if (option.first == std::chrono::minutes{0}) { - return ""; - } - else if (option.first == std::chrono::minutes{1}) { - return utils::translate(timeUnitSingular); - } - else if (option.first == std::chrono::minutes{2}) { - return utils::translate(timeUnitPlural); - } - else { - return utils::translate(timeUnitGenitive); - } - } - } - return ""; - } - - void IntervalChimePresenter::activate(std::string value) - { - for (auto const &option : intervalOptions) { - if (option.second == value) { - settings->setValue( - intervalDBRecordName, utils::to_string(option.first.count()), settings::SettingsScope::AppLocal); - reinterpret_cast(app)->suspendIdleTimer(); - app->switchWindow(gui::name::window::readyGoing); - break; - } - } - } - - void IntervalChimePresenter::initIntervalOptions() - { - intervalOptions.push_back({std::chrono::minutes{0}, utils::translate("app_bell_meditation_interval_none")}); - - const auto duration = - utils::getNumericValue(settings->getValue(meditationDBRecordName, settings::SettingsScope::AppLocal)); - if (duration == 1) { - settings->setValue(intervalDBRecordName, utils::to_string(0), settings::SettingsScope::AppLocal); - reinterpret_cast(app)->suspendIdleTimer(); - app->switchWindow(gui::name::window::readyGoing); - return; - } - - for (const auto &interval : intervalsList) { - if (interval < duration) { - intervalOptions.push_back({std::chrono::minutes{interval}, getIntervalString(interval)}); - } - } - } - - std::string IntervalChimePresenter::getIntervalString(std::uint32_t value) - { - const std::string toReplace = "%0"; - std::string temp = utils::translate("app_bell_meditation_interval_every_x_minutes"); - temp.replace(temp.find(toReplace), toReplace.size(), std::to_string(value)); - return temp; - } -} // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.hpp deleted file mode 100644 index adf11c471e049becef2e660845122ba163603a80..0000000000000000000000000000000000000000 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include -#include - -namespace app -{ - class ApplicationCommon; -} - -namespace app::meditation -{ - class IntervalChimeContract - { - public: - class View - { - public: - virtual ~View() = default; - }; - - class Presenter : public BasePresenter - { - public: - virtual ~Presenter() noexcept = default; - virtual std::vector getIntervals() const = 0; - virtual std::string getCurrentInterval() const = 0; - virtual std::string getTimeUnitName(std::string value) = 0; - virtual void activate(std::string value) = 0; - }; - }; - - class IntervalChimePresenter : public IntervalChimeContract::Presenter - { - public: - IntervalChimePresenter(app::ApplicationCommon *app, settings::Settings *settings); - - std::vector getIntervals() const override; - std::string getCurrentInterval() const override; - std::string getTimeUnitName(std::string value) override; - void activate(std::string value) override; - - private: - app::ApplicationCommon *app = nullptr; - settings::Settings *settings = nullptr; - std::vector> intervalOptions; - - void initIntervalOptions(); - std::string getIntervalString(std::uint32_t value); - }; -} // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp index 1cc13f49beaaa63ad8e1949039b8a00a44e04f4c..58567d6019b81ee33d4fe267ec6010ff0b03fbb9 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp @@ -1,32 +1,39 @@ // Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "ApplicationBellMeditationTimer.hpp" +#include "MeditationTimer.hpp" #include "MeditationCommon.hpp" #include "MeditationProgressPresenter.hpp" +#include "models/ChimeInterval.hpp" #include #include #include -#include #include namespace { constexpr std::chrono::minutes emptyValue{0}; + + std::chrono::seconds to_interval(const double ratio, std::chrono::minutes total_duration) + { + const long interval = std::chrono::seconds{total_duration}.count() * ratio; + return std::chrono::seconds{interval}; + } } // namespace namespace app::meditation { MeditationProgressPresenter::MeditationProgressPresenter(app::ApplicationCommon *app, settings::Settings *settings, - std::unique_ptr timeModel) - : app{app}, settings{settings}, timeModel{std::move(timeModel)} + std::unique_ptr timeModel, + models::ChimeInterval &chimeIntervalModel) + : app{app}, settings{settings}, timeModel{std::move(timeModel)}, chimeIntervalModel{chimeIntervalModel} { duration = std::chrono::minutes{ utils::getNumericValue(settings->getValue(meditationDBRecordName, settings::SettingsScope::AppLocal))}; - interval = std::chrono::minutes{ - utils::getNumericValue(settings->getValue(intervalDBRecordName, settings::SettingsScope::AppLocal))}; + + interval = to_interval(chimeIntervalModel.getValue().to_double(), duration); } void MeditationProgressPresenter::setTimer(std::unique_ptr &&_timer) @@ -46,7 +53,7 @@ namespace app::meditation void MeditationProgressPresenter::start() { reinterpret_cast(app)->suspendIdleTimer(); - timer->reset(std::chrono::seconds(duration), std::chrono::seconds(interval)); + timer->reset(std::chrono::seconds(duration), interval); timer->start(); } diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp index d323aeb52bcd7303c28b31d2ce6208da09ee710f..d68480ba08caf40bd3edb32db405aa10b9cd003d 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp @@ -28,6 +28,11 @@ namespace settings namespace app::meditation { + namespace models + { + class ChimeInterval; + } // namespace models + class MeditationProgressContract { public: @@ -62,8 +67,9 @@ namespace app::meditation settings::Settings *settings = nullptr; std::unique_ptr timer; std::unique_ptr timeModel; + models::ChimeInterval &chimeIntervalModel; std::chrono::minutes duration; - std::chrono::minutes interval; + std::chrono::seconds interval; static constexpr auto endWindowTimeout = std::chrono::seconds{5}; @@ -73,7 +79,8 @@ namespace app::meditation public: MeditationProgressPresenter(app::ApplicationCommon *app, settings::Settings *settings, - std::unique_ptr timeModel); + std::unique_ptr timeModel, + models::ChimeInterval &chimeIntervalModel); void setTimer(std::unique_ptr &&_timer) override; void handleUpdateTimeEvent() override; diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp index 7a1db327d8b51aeadd831968da9757b748899894..49e8596be95f36bcbe690e22175117e5a02c9bcd 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "ApplicationBellMeditationTimer.hpp" +#include "MeditationTimer.hpp" #include "MeditationCommon.hpp" #include "MeditationStyle.hpp" #include "MeditationTimerPresenter.hpp" @@ -23,25 +23,25 @@ namespace app::meditation : app{app}, settings{settings} {} - std::uint32_t MeditationTimerPresenter::getMinValue() + std::uint8_t MeditationTimerPresenter::getMinValue() { return spinnerMin; } - std::uint32_t MeditationTimerPresenter::getMaxValue() + std::uint8_t MeditationTimerPresenter::getMaxValue() { return spinnerMax; } - std::uint32_t MeditationTimerPresenter::getStepValue() + std::uint8_t MeditationTimerPresenter::getStepValue() { return spinnerStep; } - std::uint32_t MeditationTimerPresenter::getCurrentValue() + std::uint8_t MeditationTimerPresenter::getCurrentValue() { const auto value = settings->getValue(meditationDBRecordName, settings::SettingsScope::AppLocal); - auto defTimer = utils::getNumericValue(value); + auto defTimer = utils::getNumericValue(value); if (defTimer == emptyValue) { defTimer = defaultValue; } @@ -65,6 +65,6 @@ namespace app::meditation void MeditationTimerPresenter::activate(std::uint32_t value) { settings->setValue(meditationDBRecordName, utils::to_string(value), settings::SettingsScope::AppLocal); - app->switchWindow(gui::name::window::intervalChime); + app->switchWindow(windows::readyGoing); } } // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp index 58c2f0009788ab4fe61d1e613abb0a3078a65c6a..0e525c96fe2b160bdc921f0670ee5958c40a53a7 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp @@ -31,10 +31,10 @@ namespace app::meditation { public: virtual ~Presenter() noexcept = default; - virtual std::uint32_t getMinValue() = 0; - virtual std::uint32_t getMaxValue() = 0; - virtual std::uint32_t getStepValue() = 0; - virtual std::uint32_t getCurrentValue() = 0; + virtual std::uint8_t getMinValue() = 0; + virtual std::uint8_t getMaxValue() = 0; + virtual std::uint8_t getStepValue() = 0; + virtual std::uint8_t getCurrentValue() = 0; virtual std::string getTimeUnitName(std::uint32_t value) = 0; virtual void activate(std::uint32_t value) = 0; }; @@ -45,10 +45,10 @@ namespace app::meditation public: MeditationTimerPresenter(app::ApplicationCommon *app, settings::Settings *settings); - std::uint32_t getMinValue() override; - std::uint32_t getMaxValue() override; - std::uint32_t getStepValue() override; - std::uint32_t getCurrentValue() override; + std::uint8_t getMinValue() override; + std::uint8_t getMaxValue() override; + std::uint8_t getStepValue() override; + std::uint8_t getCurrentValue() override; std::string getTimeUnitName(std::uint32_t value) override; void activate(std::uint32_t value) override; diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp index c4183434e228a716cdf0dc47c22d37c8f3800719..da7058dc7545c0e8fdb1cad0eea225b54b01d264 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp @@ -1,16 +1,23 @@ // Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#include "ApplicationBellMeditationTimer.hpp" +#include "MeditationTimer.hpp" +#include "MeditationCommon.hpp" #include "ReadyGoingPresenter.hpp" +#include "models/StartDelay.hpp" namespace app::meditation { - ReadyGoingPresenter::ReadyGoingPresenter(app::ApplicationCommon *app) : app{app} + ReadyGoingPresenter::ReadyGoingPresenter(app::ApplicationCommon *app, const models::StartDelay &startDelayModel) + : app{app}, startDelayModel{startDelayModel} {} void ReadyGoingPresenter::activate() { - app->switchWindow(gui::name::window::meditationProgress); + app->switchWindow(windows::meditationProgress); + } + std::chrono::seconds ReadyGoingPresenter::getStartDelay() + { + return std::chrono::seconds{startDelayModel.getValue()}; } } // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp index 5f21628c5ab13f63a3a86928ef726f29da53e470..049fcbbe227f70d3fc3a0abf938c179a7bcd7b58 100644 --- a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp @@ -13,6 +13,11 @@ namespace app namespace app::meditation { + namespace models + { + class StartDelay; + } // namespace models + class ReadyGoingPresenterContract { public: @@ -24,16 +29,19 @@ namespace app::meditation class Presenter : public BasePresenter { public: - virtual void activate() = 0; + virtual void activate() = 0; + virtual std::chrono::seconds getStartDelay() = 0; }; }; class ReadyGoingPresenter : public ReadyGoingPresenterContract::Presenter { app::ApplicationCommon *app{}; + const models::StartDelay &startDelayModel; void activate() override; + std::chrono::seconds getStartDelay() override; public: - explicit ReadyGoingPresenter(app::ApplicationCommon *app); + ReadyGoingPresenter(app::ApplicationCommon *app, const models::StartDelay &startDelayModel); }; } // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc3c642c7f20201094fe01cbdaa696dddee8f175 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.cpp @@ -0,0 +1,117 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "SettingsPresenter.hpp" +#include "MeditationMainWindow.hpp" + +#include "models/ChimeInterval.hpp" +#include "models/ChimeVolume.hpp" +#include "models/StartDelay.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace app::list_items +{ + struct StartDelayFormatter + { + public: + StartDelayFormatter() : none(utils::translate("app_bell_meditation_interval_none")) + {} + std::string operator()(std::uint8_t value) const + { + return value == 0 ? none : std::to_string(value); + } + + private: + std::string none; + }; + + using StartDelaySpinner = gui::UIntegerSpinnerWithFormatter; + class StartDelay : public app::list_items::details::ListItemBase + { + public: + StartDelay(spinner_type::range &&range, + gui::AbstractSettingsModel &model, + const std::string &topDescription = "", + const std::string &bottomDescription = "") + : app::list_items::details::ListItemBase( + std::move(range), model, topDescription, bottomDescription) + {} + + private: + void control_bottom_description(const spinner_type::value_type &value) final + { + bottomText->setVisible(value != 0); + bottomText->setRichText(utils::language::getCorrectSecondsNumeralForm(value)); + } + }; + +} // namespace app::list_items + +namespace app::meditation +{ + using namespace gui; + SettingsPresenter::SettingsPresenter(app::ApplicationCommon *app, + models::ChimeInterval &chimeIntervalModel, + models::ChimeVolume &chimeVolumeModel, + models::StartDelay &startDelayModel) + : application{app}, chimeIntervalModel{chimeIntervalModel}, chimeVolumeModel{chimeVolumeModel}, + startDelayModel{startDelayModel} + { + auto chimeInterval = + new list_items::Fraction{list_items::Fraction::spinner_type::range{{1, 1}, {1, 2}, {1, 3}, {1, 4}}, + chimeIntervalModel, + utils::translate("app_bell_meditation_chime_interval"), + utils::translate("app_bell_meditation_chime_interval_bottom")}; + + auto startDelay = new list_items::StartDelay{list_items::StartDelay::spinner_type::range{0, 60, 1}, + startDelayModel, + utils::translate("app_bell_meditation_start_delay"), + utils::translate("common_second_lower")}; + + auto chimeVolume = new list_items::Numeric{list_items::Numeric::spinner_type::range{1, 10, 1}, + chimeVolumeModel, + utils::translate("app_bell_meditation_chime_volume")}; + + listItemsProvider = + std::make_shared(BellListItemProvider::Items{startDelay, chimeInterval, chimeVolume}); + + for (auto &item : listItemsProvider->getListItems()) { + item->setValue(); + } + } + void SettingsPresenter::loadData() + { + for (auto &item : listItemsProvider->getListItems()) { + item->setValue(); + } + } + void SettingsPresenter::saveData() + { + for (auto &item : listItemsProvider->getListItems()) { + item->getValue(); + } + } + auto SettingsPresenter::getPagesProvider() const -> std::shared_ptr + { + return listItemsProvider; + } + void SettingsPresenter::eraseProviderData() + { + listItemsProvider->clearData(); + } + void SettingsPresenter::handleEnter() + { + saveData(); + application->switchWindow( + window::bell_finished::defaultName, + BellFinishedWindowData::Factory::create("circle_success_big", MeditationMainWindow::defaultName)); + } + +} // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0e4cba833676da77dfd45de4d59d63953ada8698 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/SettingsPresenter.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "data/Contract.hpp" +#include +#include + +namespace app +{ + class ApplicationCommon; +} + +namespace app::meditation +{ + namespace models + { + class ChimeInterval; + class ChimeVolume; + class StartDelay; + } // namespace models + + class SettingsPresenter : public contract::Presenter + { + public: + SettingsPresenter(app::ApplicationCommon *app, + models::ChimeInterval &chimeIntervalModel, + models::ChimeVolume &chimeVolumeModel, + models::StartDelay &startDelayModel); + void loadData() override; + void saveData() override; + auto getPagesProvider() const -> std::shared_ptr override; + void eraseProviderData() override; + void handleEnter() override; + + private: + ApplicationCommon *application{}; + models::ChimeInterval &chimeIntervalModel; + models::ChimeVolume &chimeVolumeModel; + models::StartDelay &startDelayModel; + std::shared_ptr listItemsProvider; + }; +} // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..080dd9ebbe75a72d7bde8e45b62b3d97f5038837 --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "StatisticsPresenter.hpp" + +namespace app::meditation +{ + StatisticsPresenter::StatisticsPresenter() + {} + void StatisticsPresenter::eraseProviderData() + {} + void StatisticsPresenter::loadData() + {} + void StatisticsPresenter::saveData() + {} + auto StatisticsPresenter::getPagesProvider() const -> std::shared_ptr + { + return std::shared_ptr(); + } + void StatisticsPresenter::handleEnter() + {} +} // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9bf6567cd7a269897f5caa7ef2b56cd977b25bef --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/presenter/StatisticsPresenter.hpp @@ -0,0 +1,23 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "data/Contract.hpp" +#include + +namespace app::meditation +{ + class StatisticsPresenter : public contract::Presenter + { + public: + StatisticsPresenter(); + auto getPagesProvider() const -> std::shared_ptr override; + void loadData() override; + void saveData() override; + void eraseProviderData() override; + void handleEnter() override; + + private: + }; +} // namespace app::meditation diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.cpp deleted file mode 100644 index 39421609695babb2357c00cdd658fd28ebdaca04..0000000000000000000000000000000000000000 --- a/products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "ApplicationBellMeditationTimer.hpp" -#include "IntervalChimeWindow.hpp" -#include "MeditationStyle.hpp" - -namespace gui -{ - IntervalChimeWindow::IntervalChimeWindow( - app::ApplicationCommon *app, - std::unique_ptr &&windowPresenter) - : AppWindow(app, gui::name::window::intervalChime), presenter{std::move(windowPresenter)} - { - presenter->attach(this); - buildInterface(); - } - - void IntervalChimeWindow::buildInterface() - { - AppWindow::buildInterface(); - - statusBar->setVisible(false); - header->setTitleVisibility(false); - navBar->setVisible(false); - - body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true); - - auto topMessage = new TextFixedSize(body->firstBox); - topMessage->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h); - topMessage->setFont(style::window::font::largelight); - topMessage->setEdges(gui::RectangleEdge::None); - topMessage->activeItem = false; - topMessage->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center)); - topMessage->setText(utils::translate("app_bell_meditation_interval_chime")); - topMessage->drawUnderline(false); - - auto titles = presenter->getIntervals(); - spinner = new UTF8Spinner({titles.begin(), titles.end()}, Boundaries::Fixed); - spinner->onValueChanged = [this](const auto val) { this->onValueChanged(val); }; - spinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h); - spinner->setFont(app::meditationStyle::icStyle::text::font); - spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center)); - spinner->setFocusEdges(RectangleEdge::None); - body->getCenterBox()->addWidget(spinner); - - auto currentValue = presenter->getCurrentInterval(); - spinner->setCurrentValue(currentValue); - body->setMinMaxArrowsVisibility(currentValue == titles.front(), currentValue == titles.back()); - - bottomDescription = new Label(body->lastBox); - bottomDescription->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h); - bottomDescription->setFont(app::meditationStyle::icStyle::minute::font); - bottomDescription->setEdges(RectangleEdge::None); - bottomDescription->activeItem = false; - bottomDescription->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top)); - bottomDescription->setText(presenter->getTimeUnitName(spinner->getCurrentValue())); - - setFocusItem(spinner); - body->resize(); - } - - bool IntervalChimeWindow::onInput(const gui::InputEvent &inputEvent) - { - if (spinner->onInput(inputEvent)) { - return true; - } - - if (inputEvent.isShortRelease(gui::KeyCode::KEY_ENTER)) { - presenter->activate(spinner->getCurrentValue()); - return true; - } - - return AppWindow::onInput(inputEvent); - } - - void IntervalChimeWindow::onValueChanged(const std::string currentValue) - { - auto titles = presenter->getIntervals(); - body->setMinMaxArrowsVisibility(currentValue == titles.front(), currentValue == titles.back()); - bottomDescription->setText(presenter->getTimeUnitName(spinner->getCurrentValue())); - } -} // namespace gui diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.hpp b/products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.hpp deleted file mode 100644 index c5f2bd3500b70a8a76dba5f439c816e73f4442e2..0000000000000000000000000000000000000000 --- a/products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include -#include - -#include -#include -#include - -#include "IntervalChimePresenter.hpp" - -namespace gui -{ - class IntervalChimeWindow : public AppWindow, public app::meditation::IntervalChimeContract::View - { - public: - explicit IntervalChimeWindow( - app::ApplicationCommon *app, - std::unique_ptr &&windowPresenter); - - // virtual methods - void buildInterface() override; - bool onInput(const gui::InputEvent &inputEvent) override; - - void onValueChanged(const std::string currentValue); - - private: - std::unique_ptr presenter; - BellBaseLayout *body{}; - UTF8Spinner *spinner{}; - Label *bottomDescription{}; - }; -} // namespace gui diff --git a/products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationMainWindow.cpp b/products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationMainWindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e65bdd2d5530d17ddce91a45656b4c8a0463a9f --- /dev/null +++ b/products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationMainWindow.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "MeditationMainWindow.hpp" + +#include "SettingsWindow.hpp" +#include "StatisticsWindow.hpp" +#include "MeditationTimerWindow.hpp" + +#include +#include +#include + +namespace app::meditation +{ + using namespace gui; + MeditationMainWindow::MeditationMainWindow(app::ApplicationCommon *app) + : BellOptionWindow(app, gui::name::window::main_window) + { + addOptions(settingsOptionsList()); + setListTitle(utils::translate("app_bell_meditation_timer")); + } + + std::list