M image/assets/lang/English.json => image/assets/lang/English.json +2 -0
@@ 624,6 624,8 @@
"app_bell_powernap_session_ended_message": "<text>Hello!<br />Rise & shine</text>",
"app_bell_background_sounds_timer_off": "OFF",
"app_bell_background_sounds_timer_title": "Timer",
+ "app_bell_turn_off_question": "Turn off the device?",
+ "app_bell_goodbye": "Goodbye",
"app_bell_greeting_msg": [
"<text>Good Morning!<br />It's a Beautiful Day!</text>",
"<text>Happy Day!<br />It's a brand new morning!</text>",
M => +2 -0
@@ 38,6 38,8 @@ namespace gui::popup
return gui::popup::window::alarm_deactivated_window;
case ID::Alarm:
return gui::popup::window::alarm_window;
case ID::PowerOff:
return gui::popup::window::power_off_window;
}
return {};
M => +2 -1
@@ 25,7 25,8 @@ namespace gui
SimNotReady,
AlarmActivated,
AlarmDeactivated,
Alarm
Alarm,
PowerOff,
};
namespace window
M => +9 -2
@@ 10,11 10,18 @@ namespace app
namespace gui
{
class PowerOffPresenter
class AbstractPowerOffPresenter
{
public:
virtual ~AbstractPowerOffPresenter() = default;
virtual void powerOff() = 0;
};
class PowerOffPresenter : public AbstractPowerOffPresenter
{
public:
PowerOffPresenter(app::ApplicationCommon *app);
void powerOff();
void powerOff() override;
private:
app::ApplicationCommon *application;
M module-bsp/hal/include/hal/battery_charger/AbstractBatteryCharger.hpp => module-bsp/hal/include/hal/battery_charger/AbstractBatteryCharger.hpp +1 -0
@@ 7,6 7,7 @@
#include <queue.h>
#include <memory>
+#include <cstdint>
namespace hal::battery
{
M products/BellHybrid/apps/Application.cpp => products/BellHybrid/apps/Application.cpp +18 -1
@@ 5,16 5,19 @@
#include <common/models/AlarmModel.hpp>
+#include <common/BellPowerOffPresenter.hpp>
#include <common/popups/presenter/AlarmActivatedPresenter.hpp>
#include <common/popups/AlarmActivatedWindow.hpp>
#include <common/popups/AlarmDeactivatedWindow.hpp>
+#include <common/popups/BellTurnOffOptionWindow.hpp>
+#include <common/windows/BellTurnOffWindow.hpp>
+#include <common/windows/BellWelcomeWindow.hpp>
namespace app
{
void Application::attachPopups(const std::vector<gui::popup::ID> &popupsList)
{
using namespace gui::popup;
- app::ApplicationCommon::attachPopups(popupsList);
for (auto popup : popupsList) {
switch (popup) {
case ID::AlarmActivated:
@@ 33,6 36,20 @@ namespace app
return std::make_unique<gui::AlarmDeactivatedWindow>(app, std::move(presenter));
});
break;
+ case ID::PowerOff:
+ windowsFactory.attach(window::power_off_window, [](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique<gui::BellTurnOffOptionWindow>(app, window::power_off_window);
+ });
+ windowsFactory.attach(gui::BellTurnOffWindow::name,
+ [](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique<gui::BellTurnOffWindow>(
+ app, std::make_unique<gui::BellPowerOffPresenter>(app));
+ });
+ windowsFactory.attach(gui::BellWelcomeWindow::defaultName,
+ [](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique<gui::BellWelcomeWindow>(app);
+ });
+ break;
default:
break;
}
M products/BellHybrid/apps/application-bell-alarm/ApplicationBellAlarm.cpp => products/BellHybrid/apps/application-bell-alarm/ApplicationBellAlarm.cpp +1 -1
@@ 62,7 62,7 @@ namespace app
return std::make_unique<gui::BellAlarmSetWindow>(app, priv->alarmSetPresenter);
});
- attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated});
+ attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated, gui::popup::ID::PowerOff});
}
sys::MessagePointer ApplicationBellAlarm::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
M products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.cpp => products/BellHybrid/apps/application-bell-alarm/windows/BellAlarmWindow.cpp +1 -2
@@ 11,9 11,8 @@
#include <module-gui/gui/input/InputEvent.hpp>
#include <module-gui/gui/widgets/TextFixedSize.hpp>
#include <module-gui/gui/widgets/ThreeBox.hpp>
-#include <module-gui/gui/widgets/Image.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
namespace gui
{
M products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp => products/BellHybrid/apps/application-bell-background-sounds/ApplicationBellBackgroundSounds.cpp +2 -0
@@ 55,6 55,8 @@ namespace app
auto presenter = std::make_unique<bgSounds::BGSoundsVolumePresenter>();
return std::make_unique<gui::BGSoundsVolumeWindow>(app, std::move(presenter));
});
+
+ attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated, gui::popup::ID::PowerOff});
}
sys::MessagePointer ApplicationBellBackgroundSounds::DataReceivedHandler(sys::DataMessage *msgl,
M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp => products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp +1 -1
@@ 61,7 61,7 @@ namespace app
gui::window::name::bell_main_menu_dialog,
[](ApplicationCommon *app, const std::string &name) { return std::make_unique<gui::Dialog>(app, name); });
- attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated});
+ attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated, gui::popup::ID::PowerOff});
}
sys::MessagePointer ApplicationBellMain::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp => products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp +4 -3
@@ 7,13 7,13 @@
#include <windows/OnBoardingLanguageWindow.hpp>
#include <windows/OnBoardingFinalizeWindow.hpp>
#include <windows/OnBoardingSettingsWindow.hpp>
-#include <windows/OnBoardingWelcomeWindow.hpp>
#include <service-appmgr/Constants.hpp>
#include <service-appmgr/messages/GetCurrentDisplayLanguageResponse.hpp>
#include <apps-common/messages/OnBoardingMessages.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
+#include <common/windows/BellWelcomeWindow.hpp>
#include <application-bell-settings/models/TemperatureUnitModel.hpp>
#include <application-bell-settings/models/TimeUnitsModel.hpp>
@@ 50,7 50,8 @@ namespace app
void ApplicationBellOnBoarding::createUserInterface()
{
windowsFactory.attach(gui::name::window::main_window, [this](ApplicationCommon *app, const std::string &name) {
- return std::make_unique<gui::OnBoardingWelcomeWindow>(app, name);
+ return std::make_unique<gui::BellWelcomeWindow>(
+ app, name, [app]() { app->switchWindow(gui::window::name::onBoardingLanguageWindow); });
});
windowsFactory.attach(
M products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt => products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt +0 -2
@@ 16,7 16,6 @@ target_sources(application-bell-onboarding
windows/OnBoardingLanguageWindow.cpp
windows/OnBoardingSettingsWindow.cpp
windows/OnBoardingFinalizeWindow.cpp
- windows/OnBoardingWelcomeWindow.cpp
presenter/OnBoardingLanguageWindowPresenter.cpp
presenter/OnBoardingFinalizeWindowPresenter.cpp
@@ 24,7 23,6 @@ target_sources(application-bell-onboarding
presenter/OnBoardingFinalizeWindowPresenter.hpp
windows/OnBoardingLanguageWindow.hpp
windows/OnBoardingSettingsWindow.hpp
- windows/OnBoardingWelcomeWindow.hpp
data/OnBoardingStyle.hpp
PUBLIC
M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingFinalizeWindow.hpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingFinalizeWindow.hpp +1 -1
@@ 4,7 4,7 @@
#pragma once
#include <presenter/OnBoardingFinalizeWindowPresenter.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
namespace gui
{
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +1 -1
@@ 50,7 50,7 @@ namespace app
return std::make_unique<gui::PowerNapSessionEndedWindow>(app, std::move(presenter));
});
- attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated});
+ attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated, gui::popup::ID::PowerOff});
}
sys::MessagePointer ApplicationBellPowerNap::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp => products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp +10 -5
@@ 26,11 26,12 @@
#include "windows/BellSettingsBedtimeToneWindow.hpp"
#include "windows/BellSettingsFrontlight.hpp"
#include "windows/BellSettingsHomeViewWindow.hpp"
-#include "windows/BellSettingsTurnOffWindow.hpp"
#include "windows/BellSettingsWindow.hpp"
#include <apps-common/windows/Dialog.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
+#include <common/windows/BellTurnOffWindow.hpp>
+#include <common/popups/BellTurnOffOptionWindow.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <service-evtmgr/ScreenLightControlMessage.hpp>
@@ 120,11 121,15 @@ namespace app
return std::make_unique<gui::BellSettingsBedtimeToneWindow>(app);
});
- windowsFactory.attach(gui::window::name::bellSettingsTurnOff,
+ windowsFactory.attach(gui::BellTurnOffOptionWindow::defaultName,
[](ApplicationCommon *app, const std::string &name) {
- return std::make_unique<gui::BellSettingsTurnOffWindow>(app);
+ return std::make_unique<gui::BellTurnOffOptionWindow>(app);
});
+ windowsFactory.attach(gui::BellTurnOffWindow::name, [](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique<gui::BellTurnOffWindow>(app, std::make_unique<gui::PowerOffPresenter>(app));
+ });
+
windowsFactory.attach(
gui::BellSettingsPrewakeUpWindow::name, [this](ApplicationCommon *app, const std::string &name) {
auto chimeDurationModel = std::make_unique<bell_settings::PrewakeUpChimeDurationModel>(this);
@@ 186,7 191,7 @@ namespace app
return std::make_unique<gui::AboutYourBellWindow>(app, std::move(aboutYourBellPresenter));
});
- attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated});
+ attachPopups({gui::popup::ID::AlarmActivated, gui::popup::ID::AlarmDeactivated, gui::popup::ID::PowerOff});
}
sys::MessagePointer ApplicationBellSettings::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp)
M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt => products/BellHybrid/apps/application-bell-settings/CMakeLists.txt +0 -3
@@ 52,7 52,6 @@ target_sources(application-bell-settings
windows/BellSettingsBedtimeToneWindow.cpp
windows/BellSettingsFrontlight.cpp
windows/BellSettingsHomeViewWindow.cpp
- windows/BellSettingsTurnOffWindow.cpp
windows/BellSettingsWindow.cpp
windows/advanced/AboutYourBellWindow.cpp
windows/advanced/BellSettingsAdvancedWindow.cpp
@@ 95,7 94,6 @@ target_sources(application-bell-settings
windows/BellSettingsBedtimeToneWindow.hpp
windows/BellSettingsFrontlight.hpp
windows/BellSettingsHomeViewWindow.hpp
- windows/BellSettingsTurnOffWindow.hpp
windows/BellSettingsWindow.hpp
windows/advanced/AboutYourBellWindow.hpp
windows/advanced/BellSettingsLanguageWindow.hpp
@@ 118,7 116,6 @@ target_link_libraries(application-bell-settings
PRIVATE
app
bellgui
- bell::app-common
bell::db
bell::alarms
service-appmgr
M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/ApplicationBellSettings.hpp => products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/ApplicationBellSettings.hpp +0 -1
@@ 17,7 17,6 @@ namespace gui::window::name
inline constexpr auto bellSettingsHomeView = "BellSettingsHomeView";
inline constexpr auto bellSettingsLanguage = "BellSettingsLanguage";
inline constexpr auto bellSettingsBedtimeTone = "BellSettingsBedtimeTone";
- inline constexpr auto bellSettingsTurnOff = "BellSettingsTurnOff";
} // namespace gui::window::name
namespace app
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsFrontlight.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsFrontlight.cpp +1 -1
@@ 7,7 7,7 @@
#include <gui/input/InputEvent.hpp>
#include <apps-common/options/OptionStyle.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
#include <widgets/SideListView.hpp>
#include <widgets/BellBaseLayout.hpp>
D products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTurnOffWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTurnOffWindow.cpp +0 -29
@@ 1,29 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 "BellSettingsTurnOffWindow.hpp"
-
-#include <application-bell-settings/ApplicationBellSettings.hpp>
-
-namespace gui
-{
- BellSettingsTurnOffWindow::BellSettingsTurnOffWindow(app::ApplicationCommon *app, std::string name)
- : AppWindow(app, std::move(name))
- {
- buildInterface();
- }
-
- void BellSettingsTurnOffWindow::rebuild()
- {
- erase();
- buildInterface();
- }
-
- void BellSettingsTurnOffWindow::buildInterface()
- {
- AppWindow::buildInterface();
- statusBar->setVisible(false);
- header->setTitleVisibility(false);
- bottomBar->setVisible(false);
- }
-} /* namespace gui */
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsWindow.cpp +2 -1
@@ 9,6 9,7 @@
#include <apps-common/messages/DialogMetadataMessage.hpp>
#include <common/options/OptionBellMenu.hpp>
+#include <common/popups/BellTurnOffOptionWindow.hpp>
#include <apps-common/windows/Dialog.hpp>
namespace gui
@@ 46,7 47,7 @@ namespace gui
addWinSettings(utils::translate("app_bell_settings_alarm_settings"), BellSettingsAlarmSettingsMenuWindow::name);
addWinSettings(utils::translate("app_bell_settings_bedtime_tone"), window::name::bellSettingsBedtimeTone);
addWinSettings(utils::translate("app_bell_settings_advanced"), window::name::bellSettingsAdvanced);
- addWinSettings(utils::translate("app_bell_settings_turn_off"), window::name::bellSettingsTurnOff);
+ addWinSettings(utils::translate("app_bell_settings_turn_off"), BellTurnOffOptionWindow::defaultName);
return settingsOptionList;
}
M products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsTimeUnitsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/advanced/BellSettingsTimeUnitsWindow.cpp +1 -1
@@ 7,7 7,7 @@
#include <gui/input/InputEvent.hpp>
#include <apps-common/options/OptionStyle.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
#include <widgets/SideListView.hpp>
namespace gui
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.cpp +1 -1
@@ 8,7 8,7 @@
#include "presenter/alarm_settings/SnoozePresenter.hpp"
#include <apps-common/ApplicationCommon.hpp>
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
#include <gui/input/InputEvent.hpp>
#include <widgets/SideListView.hpp>
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsAlarmSettingsWindow.cpp +1 -1
@@ 5,7 5,7 @@
#include "BellSettingsAlarmSettingsMenuWindow.hpp"
#include "BellSettingsAlarmSettingsWindow.hpp"
#include "BellSettingsStyle.hpp"
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
#include <apps-common/options/OptionStyle.hpp>
#include <module-gui/gui/input/InputEvent.hpp>
M products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/alarm_settings/BellSettingsPrewakeUpWindow.cpp +1 -1
@@ 5,7 5,7 @@
#include "BellSettingsAlarmSettingsMenuWindow.hpp"
#include "BellSettingsPrewakeUpWindow.hpp"
#include "BellSettingsStyle.hpp"
-#include <common/BellFinishedWindow.hpp>
+#include <common/windows/BellFinishedWindow.hpp>
#include <apps-common/options/OptionStyle.hpp>
#include <module-gui/gui/input/InputEvent.hpp>
M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +10 -2
@@ 10,21 10,28 @@ target_include_directories(application-bell-common
target_sources(application-bell-common
PRIVATE
+ src/BellPowerOffPresenter.cpp
src/AlarmModel.cpp
src/TimeModel.cpp
- src/BellFinishedWindow.cpp
+ src/windows/BellFinishedWindow.cpp
+ src/windows/BellTurnOffWindow.cpp
+ src/windows/BellWelcomeWindow.cpp
src/BellSideListItemWithCallbacks.cpp
src/TimeUtils.cpp
src/popups/presenter/AlarmActivatedPresenter.cpp
src/popups/AlarmActivatedWindow.cpp
src/popups/AlarmDeactivatedWindow.cpp
+ src/popups/BellTurnOffOptionWindow.cpp
src/widgets/ListItems.cpp
src/options/BellOptionWindow.cpp
src/options/BellShortOptionWindow.cpp
src/options/OptionBellMenu.cpp
PUBLIC
- include/common/BellFinishedWindow.hpp
+ include/common/BellPowerOffPresenter.hpp
+ include/common/windows/BellFinishedWindow.hpp
+ include/common/windows/BellTurnOffWindow.hpp
+ include/common/windows/BellWelcomeWindow.hpp
include/common/TimeUtils.hpp
include/common/models/AbstractAlarmModel.hpp
include/common/models/AbstractSettingsModel.hpp
@@ 33,6 40,7 @@ target_sources(application-bell-common
include/common/popups/presenter/AlarmActivatedPresenter.hpp
include/common/popups/AlarmActivatedWindow.hpp
include/common/popups/AlarmDeactivatedWindow.hpp
+ include/common/popups/BellTurnOffOptionWindow.hpp
include/common/widgets/BellSideListItemWithCallbacks.hpp
include/common/widgets/ListItems.hpp
include/common/options/BellOptionWindow.hpp
A products/BellHybrid/apps/common/include/common/BellPowerOffPresenter.hpp => products/BellHybrid/apps/common/include/common/BellPowerOffPresenter.hpp +19 -0
@@ 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 <apps-common/popups/presenter/PowerOffPresenter.hpp>
+
+namespace gui
+{
+ class BellPowerOffPresenter : public gui::AbstractPowerOffPresenter
+ {
+ public:
+ explicit BellPowerOffPresenter(app::ApplicationCommon *app);
+ void powerOff() override;
+
+ private:
+ app::ApplicationCommon *application;
+ };
+} // namespace gui
M products/BellHybrid/apps/common/include/common/data/StyleCommon.hpp => products/BellHybrid/apps/common/include/common/data/StyleCommon.hpp +1 -0
@@ 10,4 10,5 @@ namespace gui::bell_style
{
inline constexpr auto font = ::style::window::font::supersizemelight;
inline constexpr auto font_center = ::style::window::font::largelight;
+ inline constexpr auto font_top = ::style::window::font::largelight;
} // namespace gui::bell_style
R products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTurnOffWindow.hpp => +9 -8
@@ 3,19 3,20 @@
#pragma once
-#include <application-bell-settings/ApplicationBellSettings.hpp>
-
-#include <apps-common/windows/AppWindow.hpp>
+#include <common/options/BellShortOptionWindow.hpp>
namespace gui
{
- class BellSettingsTurnOffWindow : public AppWindow
+ class BellTurnOffOptionWindow : public BellShortOptionWindow
{
public:
- explicit BellSettingsTurnOffWindow(app::ApplicationCommon *app,
- std::string name = gui::window::name::bellSettingsTurnOff);
+ static constexpr auto defaultName = "BellTurnOffOptionWindow";
+ explicit BellTurnOffOptionWindow(app::ApplicationCommon *app, const char *name = defaultName);
+
+ private:
+ std::list<Option> settingsOptionsList();
- void buildInterface() override;
- void rebuild() override;
+ const UTF8 yesStr;
+ const UTF8 noStr;
};
} /* namespace gui */
R products/BellHybrid/apps/common/include/common/BellFinishedWindow.hpp => products/BellHybrid/apps/common/include/common/windows/BellFinishedWindow.hpp +0 -0
A products/BellHybrid/apps/common/include/common/windows/BellTurnOffWindow.hpp => products/BellHybrid/apps/common/include/common/windows/BellTurnOffWindow.hpp +28 -0
@@ 0,0 1,28 @@
+// 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 <apps-common/popups/presenter/PowerOffPresenter.hpp>
+#include <apps-common/popups/WindowWithTimer.hpp>
+
+namespace gui
+{
+ class Icon;
+
+ class BellTurnOffWindow : public WindowWithTimer
+ {
+ public:
+ static constexpr auto name = "BellTurnOffWindow";
+
+ BellTurnOffWindow(app::ApplicationCommon *app, std::unique_ptr<AbstractPowerOffPresenter> presenter);
+
+ private:
+ void buildInterface() override;
+ bool onInput(const InputEvent &inputEvent) override;
+
+ Icon *icon{};
+ std::unique_ptr<AbstractPowerOffPresenter> presenter;
+ };
+
+} // namespace gui
R products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.hpp => products/BellHybrid/apps/common/include/common/windows/BellWelcomeWindow.hpp +16 -4
@@ 3,23 3,35 @@
#pragma once
-#include <BellOnBoardingNames.hpp>
#include <apps-common/windows/AppWindow.hpp>
+#include <functional>
+
namespace gui
{
class BellBaseLayout;
- class OnBoardingWelcomeWindow : public AppWindow
+ class BellWelcomeWindow : public AppWindow
{
+ static constexpr auto midline_correction = 40U;
+ static constexpr auto midline_w = 480U;
+ static constexpr auto midline_h = 1U;
+ static constexpr auto sun_logo_margin_top = 10U;
+ static constexpr auto sun_logo_margin_right = 25U;
+
public:
- explicit OnBoardingWelcomeWindow(app::ApplicationCommon *app,
- const std::string &name = gui::window::name::onBoardingLanguageWindow);
+ using Callback = std::function<void()>;
+ static constexpr auto defaultName = "BellWelcomeWindow";
+
+ explicit BellWelcomeWindow(app::ApplicationCommon *app,
+ const std::string &name = defaultName,
+ Callback onAction = {});
void buildInterface() override;
bool onInput(const InputEvent &inputEvent) override;
private:
BellBaseLayout *body{nullptr};
+ Callback onAction;
};
} /* namespace gui */
A products/BellHybrid/apps/common/src/BellPowerOffPresenter.cpp => products/BellHybrid/apps/common/src/BellPowerOffPresenter.cpp +22 -0
@@ 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 "BellPowerOffPresenter.hpp"
+
+#include <common/windows/BellWelcomeWindow.hpp>
+#include <service-appmgr/messages/UserPowerDownRequest.hpp>
+#include <system/Constants.hpp>
+
+namespace gui
+{
+ BellPowerOffPresenter::BellPowerOffPresenter(app::ApplicationCommon *app) : application(app)
+ {}
+
+ void BellPowerOffPresenter::powerOff()
+ {
+ application->switchWindow(BellWelcomeWindow::defaultName);
+ auto msg = std::make_shared<app::UserPowerDownRequest>();
+ application->bus.sendUnicast(std::move(msg), service::name::system_manager);
+ }
+
+} // namespace gui
A => +43 -0
@@ 0,0 1,43 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "popups/BellTurnOffOptionWindow.hpp"
#include <apps-common/widgets/BellBaseLayout.hpp>
#include <apps-common/ApplicationCommon.hpp>
#include <common/data/StyleCommon.hpp>
#include <common/windows/BellTurnOffWindow.hpp>
#include <i18n/i18n.hpp>
#include <options/OptionBellMenu.hpp>
namespace gui
{
BellTurnOffOptionWindow::BellTurnOffOptionWindow(app::ApplicationCommon *app, const char *name)
: BellShortOptionWindow(app, name), yesStr{utils::translate("common_yes")}, noStr{utils::translate("common_no")}
{
addOptions(settingsOptionsList());
setListTitle(utils::translate("app_bell_turn_off_question"));
optionsList->setBoundaries(Boundaries::Continuous);
optionsList->setAlignment(Alignment(Alignment::Vertical::Center));
}
std::list<Option> BellTurnOffOptionWindow::settingsOptionsList()
{
std::list<gui::Option> settingsOptionList;
auto addWinSettings = [&](const UTF8 &name, std::function<bool(Item &)> activatedCallback) {
settingsOptionList.emplace_back(std::make_unique<gui::option::OptionBellMenu>(
name, activatedCallback, [=](gui::Item &) { return true; }, this));
};
addWinSettings(noStr, [this](auto &) {
application->returnToPreviousWindow();
return true;
});
addWinSettings(yesStr, [this](auto &) {
application->switchWindow(BellTurnOffWindow::name);
return true;
});
return settingsOptionList;
}
} /* namespace gui */
R products/BellHybrid/apps/common/src/BellFinishedWindow.cpp => products/BellHybrid/apps/common/src/windows/BellFinishedWindow.cpp +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "common/BellFinishedWindow.hpp"
+#include "windows/BellFinishedWindow.hpp"
#include <apps-common/ApplicationCommon.hpp>
#include <gui/input/InputEvent.hpp>
#include <gui/widgets/Icon.hpp>
A products/BellHybrid/apps/common/src/windows/BellTurnOffWindow.cpp => products/BellHybrid/apps/common/src/windows/BellTurnOffWindow.cpp +46 -0
@@ 0,0 1,46 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "windows/BellTurnOffWindow.hpp"
+#include <gui/input/InputEvent.hpp>
+#include <gui/widgets/Icon.hpp>
+#include <i18n/i18n.hpp>
+#include <Application.hpp>
+
+namespace gui
+{
+ BellTurnOffWindow::BellTurnOffWindow(app::ApplicationCommon *app,
+ std::unique_ptr<AbstractPowerOffPresenter> presenter)
+ : WindowWithTimer(app, name), presenter(std::move(presenter))
+ {
+ buildInterface();
+
+ timerCallback = [this](Item &, sys::Timer &) {
+ this->presenter->powerOff();
+ return true;
+ };
+ }
+
+ void gui::BellTurnOffWindow::buildInterface()
+ {
+ WindowWithTimer::buildInterface();
+
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ bottomBar->setVisible(false);
+
+ icon = new Icon(this,
+ 0,
+ 0,
+ style::window_width,
+ style::window_height,
+ "bell_mudita_logo_W_G",
+ utils::translate("app_bell_goodbye"));
+ icon->text->setFont(style::window::font::verybiglight);
+ }
+ bool BellTurnOffWindow::onInput(const InputEvent &)
+ {
+ return true;
+ }
+
+} // namespace gui
R products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingWelcomeWindow.cpp => products/BellHybrid/apps/common/src/windows/BellWelcomeWindow.cpp +13 -13
@@ 1,24 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 "OnBoardingWelcomeWindow.hpp"
-#include "OnBoardingLanguageWindow.hpp"
+#include "windows/BellWelcomeWindow.hpp"
-#include <data/OnBoardingStyle.hpp>
#include <apps-common/widgets/BellBaseLayout.hpp>
#include <module-gui/gui/input/InputEvent.hpp>
#include <module-gui/gui/widgets/TextFixedSize.hpp>
+#include <i18n/i18n.hpp>
namespace gui
{
- OnBoardingWelcomeWindow::OnBoardingWelcomeWindow(app::ApplicationCommon *app, const std::string &name)
- : AppWindow(app, name)
+ BellWelcomeWindow::BellWelcomeWindow(app::ApplicationCommon *app, const std::string &name, Callback onAction)
+ : AppWindow(app, name), onAction{onAction}
{
buildInterface();
}
- void OnBoardingWelcomeWindow::buildInterface()
+ void BellWelcomeWindow::buildInterface()
{
AppWindow::buildInterface();
statusBar->setVisible(false);
@@ 32,14 31,14 @@ namespace gui
auto welcomeText = new TextFixedSize(body->centerBox);
welcomeText->setMinimumSize(style::bell_base_layout::w,
- style::bell_base_layout::center_layout_h - window::welcome::midline_correction);
+ style::bell_base_layout::center_layout_h - midline_correction);
welcomeText->setFont(style::window::font::largelight);
welcomeText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
welcomeText->drawUnderline(false);
welcomeText->setText(utils::translate("app_bell_onboarding_welcome_message"));
auto midLine = new Rect(body->centerBox, 0, 0, 0, 0);
- midLine->setMinimumSize(window::welcome::midline_w, window::welcome::midline_h);
+ midLine->setMinimumSize(midline_w, midline_h);
midLine->setEdges(RectangleEdge::Bottom);
auto informationBody = new HBox(body->lastBox);
@@ 50,11 49,10 @@ namespace gui
auto sunLogo = new ImageBox(informationBody, new Image("button_icon_sun", ImageTypeSpecifier::W_G));
sunLogo->setMinimumSizeToFitImage();
- sunLogo->setMargins(
- Margins(0, window::welcome::sun_logo_margin_top, window::welcome::sun_logo_margin_right, 0));
+ sunLogo->setMargins(Margins(0, sun_logo_margin_top, sun_logo_margin_right, 0));
auto instructionText = new TextFixedSize(informationBody);
- instructionText->setMargins(Margins(0, window::welcome::sun_logo_margin_top, 0, 0));
+ instructionText->setMargins(Margins(0, sun_logo_margin_top, 0, 0));
instructionText->setFont(style::window::font::largelight);
instructionText->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
instructionText->drawUnderline(false);
@@ 67,10 65,12 @@ namespace gui
body->resize();
}
- bool OnBoardingWelcomeWindow::onInput(const InputEvent &inputEvent)
+ bool BellWelcomeWindow::onInput(const InputEvent &inputEvent)
{
if (inputEvent.isKeyRelease(KeyCode::KEY_LF)) {
- application->switchWindow(gui::window::name::onBoardingLanguageWindow);
+ if (onAction) {
+ onAction();
+ }
}
return false;
}
M products/BellHybrid/keymap/include/keymap/KeyMap.hpp => products/BellHybrid/keymap/include/keymap/KeyMap.hpp +51 -9
@@ 4,21 4,63 @@
#pragma once
#include <gui/input/InputEvent.hpp>
+#include <bitset>
/// Key mapping structure to ease translation between PureOS key definitions and nomenclature used throughout the
/// GUI design
-enum class KeyMap
+enum class KeyMap : std::uint8_t
{
- Frontlight = static_cast<int>(gui::KeyCode::KEY_LF),
- Back = static_cast<int>(gui::KeyCode::KEY_RF),
- LightPress = static_cast<int>(gui::KeyCode::KEY_ENTER),
- RotateLeft = static_cast<int>(gui::KeyCode::KEY_DOWN),
- RotateRight = static_cast<int>(gui::KeyCode::KEY_UP),
- DeepPressUp = static_cast<int>(gui::KeyCode::KEY_LEFT),
- DeepPressDown = static_cast<int>(gui::KeyCode::KEY_RIGHT),
+ Frontlight = 0,
+ Back = 1,
+ LightPress = 2,
+ RotateLeft = 3,
+ RotateRight = 4,
+ DeepPressUp = 5,
+ DeepPressDown = 6
};
inline static KeyMap mapKey(gui::KeyCode key)
{
- return KeyMap{key};
+ switch (key) {
+ case gui::KeyCode::KEY_LF:
+ return KeyMap::Frontlight;
+ case gui::KeyCode::KEY_RF:
+ return KeyMap::Back;
+ case gui::KeyCode::KEY_ENTER:
+ return KeyMap::LightPress;
+ case gui::KeyCode::KEY_DOWN:
+ return KeyMap::RotateLeft;
+ case gui::KeyCode::KEY_UP:
+ return KeyMap::RotateRight;
+ case gui::KeyCode::KEY_LEFT:
+ return KeyMap::DeepPressUp;
+ case gui::KeyCode::KEY_RIGHT:
+ return KeyMap::DeepPressDown;
+ default:
+ assert(("Unrecognized key code"));
+ return KeyMap{};
+ }
}
+
+struct KeyStates
+{
+ using KeySet = std::bitset<32U>;
+
+ void set(KeyMap key, bool value)
+ {
+ states.set(magic_enum::enum_integer(key), value);
+ }
+ bool state(KeyMap key)
+ {
+ return states.test(magic_enum::enum_integer(key));
+ }
+
+ template <typename... Args> bool ifOnlySet(Args... args)
+ {
+ const auto mask = (... | [](auto x) { return KeySet{1UL << magic_enum::enum_integer(x)}; }(args));
+ return (states | mask) == mask;
+ }
+
+ private:
+ KeySet states;
+};
M products/BellHybrid/services/appmgr/CMakeLists.txt => products/BellHybrid/services/appmgr/CMakeLists.txt +2 -0
@@ 1,4 1,5 @@
add_library(appmgr STATIC)
+add_library(bell::appmgr ALIAS appmgr)
target_sources(appmgr
PRIVATE
@@ 6,6 7,7 @@ target_sources(appmgr
PUBLIC
include/appmgr/messages/AlarmMessage.hpp
include/appmgr/ApplicationManager.hpp
+ include/appmgr/messages/PowerOffPopupRequestParams.hpp
)
target_include_directories(appmgr
A => +16 -0
@@ 0,0 1,16 @@
// 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 <Service/Message.hpp>
#include <apps-common/popups/data/PopupRequestParams.hpp>
#include <service-appmgr/Actions.hpp>
#include <service-appmgr/messages/ActionRequest.hpp>
class PowerOffPopupRequestParams : public gui::PopupRequestParams
{
public:
PowerOffPopupRequestParams() : PopupRequestParams{gui::popup::ID::PowerOff}
{}
};
M products/BellHybrid/services/evtmgr/CMakeLists.txt => products/BellHybrid/services/evtmgr/CMakeLists.txt +15 -1
@@ 8,10 8,19 @@ target_sources(evtmgr
WorkerEvent.hpp
internal/StaticData.cpp
internal/TemperatureApi.cpp
-
+ internal/key_sequences/LongPressSequence.cpp
+ internal/key_sequences/KeySequenceMgr.cpp
internal/StaticData.hpp
screen-light-control/ScreenLightControl.cpp
backlight-handler/BacklightHandler.cpp
+
+ internal/key_sequences/AbstractKeySequence.hpp
+ internal/key_sequences/KeySequenceMgr.hpp
+ internal/key_sequences/PowerOffSequence.hpp
+ internal/key_sequences/AlarmActivateSequence.hpp
+ internal/key_sequences/AlarmDeactivateSequence.hpp
+ internal/key_sequences/ReleaseSequence.hpp
+ internal/key_sequences/LongPressSequence.hpp
PUBLIC
include/evtmgr/EventManager.hpp
include/evtmgr/api/TemperatureApi.hpp
@@ 30,5 39,10 @@ target_link_libraries(evtmgr
module-bsp
module-utils
service-evtmgr
+ bell::appmgr
sys
)
+
+if (${ENABLE_TESTS})
+ add_subdirectory(tests)
+endif()
M products/BellHybrid/services/evtmgr/EventManager.cpp => products/BellHybrid/services/evtmgr/EventManager.cpp +40 -18
@@ 1,11 1,16 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "WorkerEvent.hpp"
#include "internal/StaticData.hpp"
+#include "internal/key_sequences/KeySequenceMgr.hpp"
+#include "internal/key_sequences/PowerOffSequence.hpp"
+#include "internal/key_sequences/AlarmActivateSequence.hpp"
+#include "internal/key_sequences/AlarmDeactivateSequence.hpp"
-#include "WorkerEvent.hpp"
+#include <appmgr/messages/PowerOffPopupRequestParams.hpp>
#include <evtmgr/EventManager.hpp>
-#include <keymap/KeyMap.hpp>
+#include <service-appmgr/Controller.hpp>
#include <hal/temperature_source/TemperatureSource.hpp>
#include <system/Constants.hpp>
#include <screen-light-control/ScreenLightControl.hpp>
@@ 31,6 36,7 @@ EventManager::EventManager(const std::string &name)
: EventManagerCommon(name), temperatureSource{hal::temperature::AbstractTemperatureSource::Factory::create()},
backlightHandler(settings, this)
{
+ buildKeySequences();
updateTemperature(*temperatureSource);
onMinuteTick = [this](const time_t) { updateTemperature(*temperatureSource); };
@@ 45,24 51,11 @@ void EventManager::handleKeyEvent(sys::Message *msg)
return;
}
- auto key = mapKey(static_cast<gui::KeyCode>(kbdMessage->key.keyCode));
-
- if (kbdMessage->key.state == RawKey::State::Released) {
- if (key == KeyMap::DeepPressUp) {
- bus.sendUnicast(
- std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::ACTIVATED),
- service::name::system_manager);
- }
- else if (key == KeyMap::DeepPressDown) {
- bus.sendUnicast(
- std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::DEACTIVATED),
- service::name::system_manager);
- }
- }
-
if (kbdMessage->key.state == RawKey::State::Pressed) {
- backlightHandler.handleKeyPressed(static_cast<int>(key));
+ backlightHandler.handleKeyPressed(static_cast<int>(static_cast<gui::KeyCode>(kbdMessage->key.keyCode)));
}
+
+ keySequenceMgr->process(kbdMessage->key);
}
auto EventManager::createEventWorker() -> std::unique_ptr<WorkerEventCommon>
@@ 115,3 108,32 @@ sys::MessagePointer EventManager::DataReceivedHandler(sys::DataMessage *msgl, sy
return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
}
+void EventManager::buildKeySequences()
+{
+ KeySequenceMgr::SequenceCollection collection;
+
+ auto powerOffSeq = std::make_unique<PowerOffSequence>(*this);
+ powerOffSeq->onAction = [this]() {
+ app::manager::Controller::sendAction(
+ this, app::manager::actions::ShowPopup, std::make_unique<PowerOffPopupRequestParams>());
+ };
+ collection.emplace_back(std::move(powerOffSeq));
+
+ auto alarmActivateSeq = std::make_unique<AlarmActivateSequence>();
+ alarmActivateSeq->onAction = [this]() {
+ bus.sendUnicast(
+ std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::ACTIVATED),
+ service::name::system_manager);
+ };
+ collection.emplace_back(std::move(alarmActivateSeq));
+
+ auto alarmDeactivateSeq = std::make_unique<AlarmDeactivateSequence>();
+ alarmDeactivateSeq->onAction = [this]() {
+ bus.sendUnicast(
+ std::make_shared<sys::AlarmActivationStatusChangeRequest>(sys::AlarmActivationStatus::DEACTIVATED),
+ service::name::system_manager);
+ };
+ collection.emplace_back(std::move(alarmDeactivateSeq));
+
+ keySequenceMgr = std::make_unique<KeySequenceMgr>(std::move(collection));
+}
M products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp => products/BellHybrid/services/evtmgr/include/evtmgr/EventManager.hpp +5 -0
@@ 7,6 7,8 @@
#include "BacklightHandler.hpp"
+class KeySequenceMgr;
+
namespace hal::temperature
{
class AbstractTemperatureSource;
@@ 22,8 24,11 @@ class EventManager : public EventManagerCommon
sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
void initProductEvents() final;
auto createEventWorker() -> std::unique_ptr<WorkerEventCommon> final;
+ void buildKeySequences();
std::shared_ptr<hal::temperature::AbstractTemperatureSource> temperatureSource;
backlight::Handler backlightHandler;
+
+ std::shared_ptr<KeySequenceMgr> keySequenceMgr;
};
namespace sys
A products/BellHybrid/services/evtmgr/internal/key_sequences/AbstractKeySequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/AbstractKeySequence.hpp +66 -0
@@ 0,0 1,66 @@
+// 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 <hal/key_input/RawKey.hpp>
+
+#include <functional>
+
+class AbstractKeySequence
+{
+ template <class Cb, class... Args> static void invoke(Cb &&callback, Args &&...args)
+ {
+ if (callback) {
+ callback(args...);
+ }
+ }
+
+ public:
+ using Callback = std::function<void(const AbstractKeySequence &)>;
+
+ virtual ~AbstractKeySequence() = default;
+ virtual void process(const RawKey &key) = 0;
+
+ void trigger() const
+ {
+ invoke(onTriggered, *this);
+ }
+
+ void ready() const
+ {
+ invoke(onReady, *this);
+ }
+
+ void idle() const
+ {
+ invoke(onIdle, *this);
+ }
+
+ void abort() const
+ {
+ invoke(onAbort, *this);
+ }
+
+ void action() const
+ {
+ invoke(onAction);
+ }
+
+ void setCallbacks(Callback &&triggered, Callback &&ready, Callback &&idle, Callback &&abort)
+ {
+ onTriggered = triggered;
+ onReady = ready;
+ onIdle = idle;
+ onAbort = abort;
+ }
+
+ /// Used to inject custom action into key sequence
+ std::function<void()> onAction;
+
+ private:
+ Callback onTriggered;
+ Callback onReady;
+ Callback onIdle;
+ Callback onAbort;
+};
A products/BellHybrid/services/evtmgr/internal/key_sequences/AlarmActivateSequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/AlarmActivateSequence.hpp +13 -0
@@ 0,0 1,13 @@
+// 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 "ReleaseSequence.hpp"
+
+class AlarmActivateSequence : public ReleaseSequence
+{
+ public:
+ AlarmActivateSequence() : ReleaseSequence(KeyMap::DeepPressUp)
+ {}
+};
A products/BellHybrid/services/evtmgr/internal/key_sequences/AlarmDeactivateSequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/AlarmDeactivateSequence.hpp +13 -0
@@ 0,0 1,13 @@
+// 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 "ReleaseSequence.hpp"
+
+class AlarmDeactivateSequence : public ReleaseSequence
+{
+ public:
+ AlarmDeactivateSequence() : ReleaseSequence(KeyMap::DeepPressDown)
+ {}
+};
A products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.cpp => products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.cpp +70 -0
@@ 0,0 1,70 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "KeySequenceMgr.hpp"
+
+KeySequenceMgr::KeySequenceMgr(std::vector<std::unique_ptr<AbstractKeySequence>> collection)
+ : sequenceCollection(std::move(collection))
+{
+ auto onIdle = [this](auto &seq) {
+ removeFromInProgressList(seq);
+ actionIfPossible(seq);
+ };
+ auto onTriggered = [this](auto &seq) { addToInProgressList(seq); };
+ auto onReady = [this](auto &seq) {
+ moveToReadyList(seq);
+ actionIfPossible(seq);
+ };
+ auto onAbort = [this](auto &seq) {
+ removeFromInProgressList(seq);
+ removeFromReadyList(seq);
+ };
+
+ for (auto &seq : sequenceCollection) {
+ seq->setCallbacks(onTriggered, onReady, onIdle, onAbort);
+ }
+}
+void KeySequenceMgr::process(const RawKey &key)
+{
+ for (const auto &seq : sequenceCollection) {
+ seq->process(key);
+ }
+}
+void KeySequenceMgr::moveToReadyList(const AbstractKeySequence &seq)
+{
+ const auto res = std::find(inProgressSequences.begin(), inProgressSequences.end(), &seq);
+ if (res != inProgressSequences.end()) {
+ readySequences.emplace_back(&seq);
+ inProgressSequences.remove(&seq);
+ }
+}
+void KeySequenceMgr::actionIfPossible(const AbstractKeySequence &seq)
+{
+ if (inProgressSequences.empty()) {
+ if (const auto s = readySequences.back(); s != nullptr) {
+ s->action();
+ readySequences.clear();
+ }
+ }
+}
+bool KeySequenceMgr::searchInReadyList(const AbstractKeySequence &seq)
+{
+ return std::find(readySequences.begin(), readySequences.end(), &seq) != readySequences.end();
+}
+void KeySequenceMgr::removeFromInProgressList(const AbstractKeySequence &seq)
+{
+ const auto result = std::find(inProgressSequences.begin(), inProgressSequences.end(), &seq);
+ if (result != inProgressSequences.end()) {
+ inProgressSequences.remove(&seq);
+ }
+}
+void KeySequenceMgr::removeFromReadyList(const AbstractKeySequence &seq)
+{
+ if (searchInReadyList(seq)) {
+ readySequences.remove(&seq);
+ }
+}
+void KeySequenceMgr::addToInProgressList(const AbstractKeySequence &seq)
+{
+ inProgressSequences.emplace_back(&seq);
+}
A products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/KeySequenceMgr.hpp +32 -0
@@ 0,0 1,32 @@
+// 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 <memory>
+#include <list>
+
+#include "AbstractKeySequence.hpp"
+
+class KeySequenceMgr
+{
+ public:
+ using SequenceCollection = std::vector<std::unique_ptr<AbstractKeySequence>>;
+ explicit KeySequenceMgr(SequenceCollection collection);
+
+ void process(const RawKey &key);
+
+ private:
+ void actionIfPossible(const AbstractKeySequence &seq);
+
+ void moveToReadyList(const AbstractKeySequence &seq);
+ bool searchInReadyList(const AbstractKeySequence &seq);
+ void removeFromReadyList(const AbstractKeySequence &seq);
+
+ void addToInProgressList(const AbstractKeySequence &seq);
+ void removeFromInProgressList(const AbstractKeySequence &seq);
+
+ SequenceCollection sequenceCollection;
+ std::list<const AbstractKeySequence *> inProgressSequences;
+ std::list<const AbstractKeySequence *> readySequences;
+};
A products/BellHybrid/services/evtmgr/internal/key_sequences/LongPressSequence.cpp => products/BellHybrid/services/evtmgr/internal/key_sequences/LongPressSequence.cpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "LongPressSequence.hpp"
+
+LongPressSequence::LongPressSequence(KeyMap keyToScan, sys::Service &service, std::chrono::milliseconds timeout)
+ : keyToScan{keyToScan}
+{
+ timerHandle = sys::TimerFactory::createSingleShotTimer(&service, "lpressseq", timeout, [this](auto &) {
+ state = State::Ready;
+ ready();
+ });
+}
+void LongPressSequence::process(const RawKey &key)
+{
+ keyStates.set(mapKey(static_cast<gui::KeyCode>(key.keyCode)), key.state == RawKey::State::Pressed);
+
+ if (gate = keyStates.state(keyToScan) && not keyStates.ifOnlySet(keyToScan); gate) {
+ if (state != State::Idle) {
+ timerHandle.stop();
+ state = State::Idle;
+ abort();
+ }
+ return;
+ }
+
+ if (keyStates.state(keyToScan) && state == State::Idle) {
+ timerHandle.stop();
+ timerHandle.start();
+ state = State::InProgress;
+ trigger();
+ }
+
+ if (not keyStates.state(keyToScan) && state != State::Idle) {
+ timerHandle.stop();
+ state = State::Idle;
+ idle();
+ }
+}
A products/BellHybrid/services/evtmgr/internal/key_sequences/LongPressSequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/LongPressSequence.hpp +30 -0
@@ 0,0 1,30 @@
+// 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 "AbstractKeySequence.hpp"
+#include <keymap/KeyMap.hpp>
+#include <Timers/TimerFactory.hpp>
+
+class LongPressSequence : public AbstractKeySequence
+{
+ public:
+ enum class State
+ {
+ Idle,
+ InProgress,
+ Ready
+ };
+ LongPressSequence(KeyMap keyToScan, sys::Service &service, std::chrono::milliseconds timeout);
+
+ void process(const RawKey &key) override;
+
+ private:
+ bool gate{false};
+ KeyStates keyStates;
+ KeyMap keyToScan;
+ State state = State::Idle;
+ std::chrono::milliseconds timeout;
+ sys::TimerHandle timerHandle;
+};
A products/BellHybrid/services/evtmgr/internal/key_sequences/PowerOffSequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/PowerOffSequence.hpp +15 -0
@@ 0,0 1,15 @@
+// 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 "LongPressSequence.hpp"
+
+class PowerOffSequence : public LongPressSequence
+{
+ public:
+ explicit PowerOffSequence(sys::Service &service,
+ std::chrono::milliseconds timeout = std::chrono::milliseconds{5000})
+ : LongPressSequence(KeyMap::Back, service, timeout)
+ {}
+};
A products/BellHybrid/services/evtmgr/internal/key_sequences/ReleaseSequence.hpp => products/BellHybrid/services/evtmgr/internal/key_sequences/ReleaseSequence.hpp +28 -0
@@ 0,0 1,28 @@
+// 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 "AbstractKeySequence.hpp"
+#include <keymap/KeyMap.hpp>
+
+class ReleaseSequence : public AbstractKeySequence
+{
+ public:
+ explicit ReleaseSequence(KeyMap key) : mappedKey{key}
+ {}
+ void process(const RawKey &key) override
+ {
+ if (mapKey(static_cast<gui::KeyCode>(key.keyCode)) != mappedKey) {
+ return;
+ }
+
+ if (key.state == RawKey::State::Released) {
+ trigger();
+ ready();
+ }
+ }
+
+ private:
+ KeyMap mappedKey;
+};
A products/BellHybrid/services/evtmgr/tests/CMakeLists.txt => products/BellHybrid/services/evtmgr/tests/CMakeLists.txt +10 -0
@@ 0,0 1,10 @@
+add_catch2_executable(
+ NAME
+ bell_evtmgr
+ SRCS
+ unittest_KeySequenceMgr.cpp
+ LIBS
+ bell::evtmgr
+ INCLUDE
+ $<TARGET_PROPERTY:bell::evtmgr,INCLUDE_DIRECTORIES>
+)
A products/BellHybrid/services/evtmgr/tests/unittest_KeySequenceMgr.cpp => products/BellHybrid/services/evtmgr/tests/unittest_KeySequenceMgr.cpp +429 -0
@@ 0,0 1,429 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#define CATCH_CONFIG_MAIN
+
+#include <catch2/catch.hpp>
+#include <internal/key_sequences/KeySequenceMgr.hpp>
+#include <keymap/KeyMap.hpp>
+
+namespace
+{
+ enum class State
+ {
+ Idle,
+ InProgress,
+ Ready
+ };
+
+ class TwoKeysSequence : public AbstractKeySequence
+ {
+ public:
+ explicit TwoKeysSequence(KeyMap keyToScan1, KeyMap keyToScan2) : keyToScan1{keyToScan1}, keyToScan2{keyToScan2}
+ {}
+ void process(const RawKey &key) override
+ {
+ const auto mappedKey = mapKey(static_cast<gui::KeyCode>(key.keyCode));
+ if (mappedKey != keyToScan1 && mappedKey != keyToScan2) {
+ return;
+ }
+
+ if (mappedKey == keyToScan1) {
+ key1Pressed = key.state == RawKey::State::Pressed;
+ }
+ if (mappedKey == keyToScan2) {
+ key2Pressed = key.state == RawKey::State::Pressed;
+ }
+
+ if (key1Pressed && key2Pressed && state == State::Idle) {
+ state = State::InProgress;
+ trigger();
+ }
+
+ if (not key1Pressed || not key2Pressed) {
+ state = State::Idle;
+ idle();
+ }
+ }
+
+ void make_ready()
+ {
+ state = State::Ready;
+ ready();
+ }
+
+ private:
+ bool key1Pressed{false};
+ bool key2Pressed{false};
+ KeyMap keyToScan1;
+ KeyMap keyToScan2;
+ State state = State::Idle;
+ };
+
+ class LongPressSequence : public AbstractKeySequence
+ {
+ public:
+ explicit LongPressSequence(KeyMap keyToScan) : keyToScan{keyToScan}
+ {}
+ void process(const RawKey &key) override
+ {
+ keyStates.set(mapKey(static_cast<gui::KeyCode>(key.keyCode)), key.state == RawKey::State::Pressed);
+
+ if (gate = keyStates.state(keyToScan) && not keyStates.ifOnlySet(keyToScan); gate) {
+ if (state != State::Idle) {
+ state = State::Idle;
+ abort();
+ }
+ return;
+ }
+
+ if (keyStates.state(keyToScan) && state == State::Idle) {
+ state = State::InProgress;
+ trigger();
+ }
+
+ if (not keyStates.state(keyToScan) && state != State::Idle) {
+ state = State::Idle;
+ idle();
+ }
+ }
+
+ void make_ready()
+ {
+ state = State::Ready;
+ ready();
+ }
+
+ private:
+ bool gate{false};
+ KeyStates keyStates;
+
+ KeyMap keyToScan;
+ State state = State::Idle;
+ };
+
+ RawKey make_press_back()
+ {
+ RawKey rawKey{};
+ rawKey.state = RawKey::State::Pressed;
+ rawKey.keyCode = bsp::KeyCodes::FnRight;
+ return rawKey;
+ }
+
+ RawKey make_release_back()
+ {
+ RawKey rawKey{};
+ rawKey.state = RawKey::State::Released;
+ rawKey.keyCode = bsp::KeyCodes::FnRight;
+ return rawKey;
+ }
+
+ RawKey make_press_frontlight()
+ {
+ RawKey rawKey{};
+ rawKey.state = RawKey::State::Pressed;
+ rawKey.keyCode = bsp::KeyCodes::FnLeft;
+ return rawKey;
+ }
+
+ RawKey make_release_frontlight()
+ {
+ RawKey rawKey{};
+ rawKey.state = RawKey::State::Released;
+ rawKey.keyCode = bsp::KeyCodes::FnLeft;
+ return rawKey;
+ }
+
+} // namespace
+
+TEST_CASE("Single long press")
+{
+ std::uint8_t actionTriggered{};
+ KeySequenceMgr::SequenceCollection collection;
+
+ auto mockLongPressBack = std::make_unique<LongPressSequence>(KeyMap::Back);
+ mockLongPressBack->onAction = [&actionTriggered]() { actionTriggered++; };
+ LongPressSequence *mockRef = mockLongPressBack.get();
+
+ collection.emplace_back(std::move(mockLongPressBack));
+ KeySequenceMgr keySequenceMgr{std::move(collection)};
+
+ SECTION("Short press&release")
+ {
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered);
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered);
+ }
+
+ SECTION("Long press without release")
+ {
+ keySequenceMgr.process(make_press_back());
+ mockRef->make_ready();
+ CHECK(actionTriggered == 1);
+ }
+
+ SECTION("Valid sequence")
+ {
+ keySequenceMgr.process(make_press_back());
+ mockRef->make_ready();
+ keySequenceMgr.process(make_release_back());
+ CHECK(actionTriggered == 1);
+ }
+}
+
+TEST_CASE("Many long press sequences")
+{
+ KeySequenceMgr::SequenceCollection collection;
+
+ std::uint8_t actionTriggered_1{};
+ auto longPressBack_1 = std::make_unique<LongPressSequence>(KeyMap::Back);
+ longPressBack_1->onAction = [&actionTriggered_1]() { actionTriggered_1++; };
+ LongPressSequence *ref_1 = longPressBack_1.get();
+ collection.emplace_back(std::move(longPressBack_1));
+
+ std::uint8_t actionTriggered_2{};
+ auto longPressBack_2 = std::make_unique<LongPressSequence>(KeyMap::Back);
+ longPressBack_2->onAction = [&actionTriggered_2]() { actionTriggered_2++; };
+ LongPressSequence *ref_2 = longPressBack_2.get();
+ collection.emplace_back(std::move(longPressBack_2));
+
+ std::uint8_t actionTriggered_3{};
+ auto longPressBack_3 = std::make_unique<LongPressSequence>(KeyMap::Back);
+ longPressBack_3->onAction = [&actionTriggered_3]() { actionTriggered_3++; };
+ LongPressSequence *ref_3 = longPressBack_3.get();
+ collection.emplace_back(std::move(longPressBack_3));
+
+ KeySequenceMgr keySequenceMgr{std::move(collection)};
+
+ SECTION("Third sequence ready -> ought be invoked")
+ {
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ ref_1->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ ref_2->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ ref_3->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+ }
+
+ SECTION("Two sequences ready & release -> only second sequence ought to be invoked")
+ {
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ ref_1->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ ref_2->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(actionTriggered_2 == 1);
+ CHECK(not actionTriggered_3);
+ }
+
+ SECTION("First sequence ready -> should be invoked")
+ {
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ ref_1->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(actionTriggered_1 == 1);
+ CHECK(not actionTriggered_2);
+ }
+
+ SECTION("Second sequence ready -> should be invoked")
+ {
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ ref_1->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ ref_2->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(actionTriggered_2 == 1);
+ CHECK(not actionTriggered_3);
+ }
+
+ SECTION("Press&release without ready -> no action ought to be invoked")
+ {
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ }
+}
+
+TEST_CASE("Two keys sequence")
+{
+ KeySequenceMgr::SequenceCollection collection;
+
+ std::uint8_t actionTriggered_1{};
+ auto sequence = std::make_unique<TwoKeysSequence>(KeyMap::Back, KeyMap::Frontlight);
+ sequence->onAction = [&actionTriggered_1]() { actionTriggered_1++; };
+ TwoKeysSequence *ref_1 = sequence.get();
+ collection.emplace_back(std::move(sequence));
+
+ KeySequenceMgr keySequenceMgr{std::move(collection)};
+
+ SECTION("Valid sequence -> action ought to be invoked regardless of the type of the key release")
+ {
+ keySequenceMgr.process(make_press_frontlight());
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+
+ ref_1->make_ready();
+ CHECK(actionTriggered_1 == 1);
+
+ keySequenceMgr.process(make_release_frontlight());
+ CHECK(actionTriggered_1 == 1);
+ keySequenceMgr.process(make_release_back());
+ CHECK(actionTriggered_1 == 1);
+ }
+
+ SECTION("Key release in the middle of sequence -> no action ought to be invoked")
+ {
+ keySequenceMgr.process(make_press_frontlight());
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+
+ keySequenceMgr.process(make_release_back());
+ ref_1->make_ready();
+ CHECK(not actionTriggered_1);
+
+ keySequenceMgr.process(make_release_frontlight());
+ CHECK(not actionTriggered_1);
+ }
+}
+
+TEST_CASE("Two keys sequence type mixed with long press sequences")
+{
+ KeySequenceMgr::SequenceCollection collection;
+
+ std::uint8_t actionTriggered_1{};
+ auto sequence1 = std::make_unique<LongPressSequence>(KeyMap::Back);
+ sequence1->onAction = [&actionTriggered_1]() { actionTriggered_1++; };
+ // LongPressSequence *ref_1 = sequence1.get();
+ collection.emplace_back(std::move(sequence1));
+
+ std::uint8_t actionTriggered_2{};
+ auto sequence2 = std::make_unique<LongPressSequence>(KeyMap::Back);
+ sequence2->onAction = [&actionTriggered_2]() { actionTriggered_2++; };
+ // LongPressSequence *ref_2 = sequence2.get();
+ collection.emplace_back(std::move(sequence2));
+
+ std::uint8_t actionTriggered_3{};
+ auto sequence3 = std::make_unique<TwoKeysSequence>(KeyMap::Back, KeyMap::Frontlight);
+ sequence3->onAction = [&actionTriggered_3]() { actionTriggered_3++; };
+ TwoKeysSequence *ref_3 = sequence3.get();
+ collection.emplace_back(std::move(sequence3));
+
+ KeySequenceMgr keySequenceMgr{std::move(collection)};
+
+ SECTION("Interrupt third sequence")
+ {
+ keySequenceMgr.process(make_press_back());
+ keySequenceMgr.process(make_press_frontlight());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ keySequenceMgr.process(make_release_frontlight());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+ }
+
+ SECTION("Two keys sequence ready, back pressed first")
+ {
+ keySequenceMgr.process(make_press_back());
+ keySequenceMgr.process(make_press_frontlight());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ ref_3->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+
+ keySequenceMgr.process(make_release_frontlight());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+ }
+
+ SECTION("Two keys sequence ready, frontlight pressed first")
+ {
+ keySequenceMgr.process(make_press_frontlight());
+ keySequenceMgr.process(make_press_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(not actionTriggered_3);
+
+ ref_3->make_ready();
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+
+ keySequenceMgr.process(make_release_back());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+
+ keySequenceMgr.process(make_release_frontlight());
+ CHECK(not actionTriggered_1);
+ CHECK(not actionTriggered_2);
+ CHECK(actionTriggered_3 == 1);
+ }
+}
M products/BellHybrid/sys/CMakeLists.txt => products/BellHybrid/sys/CMakeLists.txt +1 -1
@@ 15,6 15,6 @@ target_include_directories(sys
target_link_libraries(sys
PRIVATE
- appmgr
+ bell::appmgr
module-sys
)