diff options
Diffstat (limited to 'src/displayapp')
| -rw-r--r-- | src/displayapp/Apps.h | 1 | ||||
| -rw-r--r-- | src/displayapp/DisplayApp.cpp | 15 | ||||
| -rw-r--r-- | src/displayapp/DisplayApp.h | 3 | ||||
| -rw-r--r-- | src/displayapp/DisplayAppRecovery.cpp | 1 | ||||
| -rw-r--r-- | src/displayapp/DisplayAppRecovery.h | 2 | ||||
| -rw-r--r-- | src/displayapp/Messages.h | 1 | ||||
| -rw-r--r-- | src/displayapp/screens/Alarm.cpp | 343 | ||||
| -rw-r--r-- | src/displayapp/screens/Alarm.h | 65 | ||||
| -rw-r--r-- | src/displayapp/screens/ApplicationList.cpp | 2 |
9 files changed, 432 insertions, 1 deletions
diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index 3cbaa9e..3b125d4 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -11,6 +11,7 @@ namespace Pinetime { NotificationsPreview, Notifications, FlashLight, + Alarm, QuickSettings, Settings, SettingTimeFormat, diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index f84bf57..a841f1e 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -1,5 +1,6 @@ #include "displayapp/DisplayApp.h" #include <libraries/log/nrf_log.h> +#include "displayapp/screens/Alarm.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/datetime/DateTimeController.h" @@ -73,6 +74,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Controllers::Settings& settingsController, Pinetime::Controllers::MotorController& motorController, Pinetime::Controllers::MotionController& motionController, + Pinetime::Controllers::AlarmController& alarmController, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler) : lcd {lcd}, @@ -86,6 +88,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, settingsController {settingsController}, motorController {motorController}, motionController {motionController}, + alarmController {alarmController}, brightnessController {brightnessController}, touchHandler {touchHandler} { } @@ -176,6 +179,14 @@ void DisplayApp::Refresh() { case Messages::NewNotification: LoadApp(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down); break; + case Messages::AlarmTriggered: + if (currentApp == Apps::Alarm) { + auto* alarm = static_cast<Screens::Alarm*>(currentScreen.get()); + alarm->SetAlerting(); + } else { + LoadApp(Apps::Alarm); + } + break; case Messages::TouchEvent: { if (state != States::Running) { break; @@ -324,6 +335,10 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) this, notificationManager, systemTask->nimble().alertService(), motorController, *systemTask, Screens::Notifications::Modes::Preview); ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp); break; + case Apps::Alarm: + currentScreen = std::make_unique<Screens::Alarm>(this, alarmController, settingsController, *systemTask); + break; + // Settings case Apps::QuickSettings: currentScreen = std::make_unique<Screens::QuickSettings>( diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index b79952d..b5186dd 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -13,6 +13,7 @@ #include "components/firmwarevalidator/FirmwareValidator.h" #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include "components/alarm/AlarmController.h" #include "touchhandler/TouchHandler.h" #include "displayapp/Messages.h" @@ -55,6 +56,7 @@ namespace Pinetime { Controllers::Settings& settingsController, Pinetime::Controllers::MotorController& motorController, Pinetime::Controllers::MotionController& motionController, + Pinetime::Controllers::AlarmController& alarmController, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler); void Start(System::BootErrors error); @@ -79,6 +81,7 @@ namespace Pinetime { Pinetime::Controllers::Settings& settingsController; Pinetime::Controllers::MotorController& motorController; Pinetime::Controllers::MotionController& motionController; + Pinetime::Controllers::AlarmController& alarmController; Pinetime::Controllers::BrightnessController &brightnessController; Pinetime::Controllers::TouchHandler& touchHandler; diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index a33308f..4a3ddf6 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -20,6 +20,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, Controllers::Settings& settingsController, Pinetime::Controllers::MotorController& motorController, Pinetime::Controllers::MotionController& motionController, + Pinetime::Controllers::AlarmController& alarmController, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler) : lcd {lcd}, bleController {bleController} { diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 8f25cbe..b358c11 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -32,6 +32,7 @@ namespace Pinetime { class TouchHandler; class MotorController; class TimerController; + class AlarmController; class BrightnessController; } @@ -53,6 +54,7 @@ namespace Pinetime { Controllers::Settings& settingsController, Pinetime::Controllers::MotorController& motorController, Pinetime::Controllers::MotionController& motionController, + Pinetime::Controllers::AlarmController& alarmController, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::TouchHandler& touchHandler); void Start(); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index c27c5e5..2891d90 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -18,6 +18,7 @@ namespace Pinetime { UpdateTimeOut, DimScreen, RestoreBrightness, + AlarmTriggered, Clock, }; } diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp new file mode 100644 index 0000000..879e50d --- /dev/null +++ b/src/displayapp/screens/Alarm.cpp @@ -0,0 +1,343 @@ +/* Copyright (C) 2021 mruss77, Florian + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ +#include "displayapp/screens/Alarm.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" + +using namespace Pinetime::Applications::Screens; +using Pinetime::Controllers::AlarmController; + +static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { + auto* screen = static_cast<Alarm*>(obj->user_data); + screen->OnButtonEvent(obj, event); +} + +static void StopAlarmTaskCallback(lv_task_t* task) { + auto* screen = static_cast<Alarm*>(task->user_data); + screen->StopAlerting(); +} + +Alarm::Alarm(DisplayApp* app, + Controllers::AlarmController& alarmController, + Pinetime::Controllers::Settings& settingsController, + System::SystemTask& systemTask) + : Screen(app), alarmController {alarmController}, settingsController {settingsController}, systemTask {systemTask} { + + time = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + alarmHours = alarmController.Hours(); + alarmMinutes = alarmController.Minutes(); + lv_label_set_text_fmt(time, "%02hhu:%02hhu", alarmHours, alarmMinutes); + + lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -25); + + lblampm = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); + lv_obj_set_style_local_text_color(lblampm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + lv_label_set_text_static(lblampm, " "); + lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); + + btnHoursUp = lv_btn_create(lv_scr_act(), nullptr); + btnHoursUp->user_data = this; + lv_obj_set_event_cb(btnHoursUp, btnEventHandler); + lv_obj_set_size(btnHoursUp, 60, 40); + lv_obj_align(btnHoursUp, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, -85); + txtHrUp = lv_label_create(btnHoursUp, nullptr); + lv_label_set_text_static(txtHrUp, "+"); + + btnHoursDown = lv_btn_create(lv_scr_act(), nullptr); + btnHoursDown->user_data = this; + lv_obj_set_event_cb(btnHoursDown, btnEventHandler); + lv_obj_set_size(btnHoursDown, 60, 40); + lv_obj_align(btnHoursDown, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, 35); + txtHrDown = lv_label_create(btnHoursDown, nullptr); + lv_label_set_text_static(txtHrDown, "-"); + + btnMinutesUp = lv_btn_create(lv_scr_act(), nullptr); + btnMinutesUp->user_data = this; + lv_obj_set_event_cb(btnMinutesUp, btnEventHandler); + lv_obj_set_size(btnMinutesUp, 60, 40); + lv_obj_align(btnMinutesUp, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -20, -85); + txtMinUp = lv_label_create(btnMinutesUp, nullptr); + lv_label_set_text_static(txtMinUp, "+"); + + btnMinutesDown = lv_btn_create(lv_scr_act(), nullptr); + btnMinutesDown->user_data = this; + lv_obj_set_event_cb(btnMinutesDown, btnEventHandler); + lv_obj_set_size(btnMinutesDown, 60, 40); + lv_obj_align(btnMinutesDown, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -20, 35); + txtMinDown = lv_label_create(btnMinutesDown, nullptr); + lv_label_set_text_static(txtMinDown, "-"); + + btnStop = lv_btn_create(lv_scr_act(), nullptr); + btnStop->user_data = this; + lv_obj_set_event_cb(btnStop, btnEventHandler); + lv_obj_set_size(btnStop, 115, 50); + lv_obj_align(btnStop, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_set_style_local_bg_color(btnStop, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); + txtStop = lv_label_create(btnStop, nullptr); + lv_label_set_text_static(txtStop, Symbols::stop); + lv_obj_set_hidden(btnStop, true); + + btnRecur = lv_btn_create(lv_scr_act(), nullptr); + btnRecur->user_data = this; + lv_obj_set_event_cb(btnRecur, btnEventHandler); + lv_obj_set_size(btnRecur, 115, 50); + lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + txtRecur = lv_label_create(btnRecur, nullptr); + SetRecurButtonState(); + + btnInfo = lv_btn_create(lv_scr_act(), nullptr); + btnInfo->user_data = this; + lv_obj_set_event_cb(btnInfo, btnEventHandler); + lv_obj_set_size(btnInfo, 50, 40); + lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_CENTER, 0, -85); + txtInfo = lv_label_create(btnInfo, nullptr); + lv_label_set_text_static(txtInfo, "i"); + + enableSwitch = lv_switch_create(lv_scr_act(), nullptr); + enableSwitch->user_data = this; + lv_obj_set_event_cb(enableSwitch, btnEventHandler); + lv_obj_set_size(enableSwitch, 100, 50); + // Align to the center of 115px from edge + lv_obj_align(enableSwitch, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 7, 0); + + UpdateAlarmTime(); + + if (alarmController.State() == Controllers::AlarmController::AlarmState::Alerting) { + SetAlerting(); + } else { + SetSwitchState(LV_ANIM_OFF); + } +} + +Alarm::~Alarm() { + if (alarmController.State() == AlarmController::AlarmState::Alerting) { + StopAlerting(); + } + lv_obj_clean(lv_scr_act()); +} + +void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { + using Pinetime::Controllers::AlarmController; + if (event == LV_EVENT_CLICKED) { + if (obj == btnStop) { + StopAlerting(); + return; + } + if (obj == btnInfo) { + ShowInfo(); + return; + } + if (obj == btnMessage) { + HideInfo(); + return; + } + if (obj == enableSwitch) { + if (lv_switch_get_state(enableSwitch)) { + alarmController.ScheduleAlarm(); + } else { + alarmController.DisableAlarm(); + } + return; + } + // If any other button was pressed, disable the alarm + // this is to make it clear that the alarm won't be set until it is turned back on + if (alarmController.State() == AlarmController::AlarmState::Set) { + alarmController.DisableAlarm(); + lv_switch_off(enableSwitch, LV_ANIM_ON); + } + if (obj == btnMinutesUp) { + if (alarmMinutes >= 59) { + alarmMinutes = 0; + } else { + alarmMinutes++; + } + UpdateAlarmTime(); + return; + } + if (obj == btnMinutesDown) { + if (alarmMinutes == 0) { + alarmMinutes = 59; + } else { + alarmMinutes--; + } + UpdateAlarmTime(); + return; + } + if (obj == btnHoursUp) { + if (alarmHours >= 23) { + alarmHours = 0; + } else { + alarmHours++; + } + UpdateAlarmTime(); + return; + } + if (obj == btnHoursDown) { + if (alarmHours == 0) { + alarmHours = 23; + } else { + alarmHours--; + } + UpdateAlarmTime(); + return; + } + if (obj == btnRecur) { + ToggleRecurrence(); + } + } +} + +bool Alarm::OnButtonPushed() { + if (txtMessage != nullptr && btnMessage != nullptr) { + HideInfo(); + return true; + } + if (alarmController.State() == AlarmController::AlarmState::Alerting) { + StopAlerting(); + return true; + } + return false; +} + +bool Alarm::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + // Don't allow closing the screen by swiping while the alarm is alerting + return alarmController.State() == AlarmController::AlarmState::Alerting && event == TouchEvents::SwipeDown; +} + +void Alarm::UpdateAlarmTime() { + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { + switch (alarmHours) { + case 0: + lv_label_set_text_static(lblampm, "AM"); + lv_label_set_text_fmt(time, "%02d:%02d", 12, alarmMinutes); + break; + case 1 ... 11: + lv_label_set_text_static(lblampm, "AM"); + lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes); + break; + case 12: + lv_label_set_text_static(lblampm, "PM"); + lv_label_set_text_fmt(time, "%02d:%02d", 12, alarmMinutes); + break; + case 13 ... 23: + lv_label_set_text_static(lblampm, "PM"); + lv_label_set_text_fmt(time, "%02d:%02d", alarmHours - 12, alarmMinutes); + break; + } + } else { + lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes); + } + alarmController.SetAlarmTime(alarmHours, alarmMinutes); +} + +void Alarm::SetAlerting() { + lv_obj_set_hidden(enableSwitch, true); + lv_obj_set_hidden(btnStop, false); + taskStopAlarm = lv_task_create(StopAlarmTaskCallback, pdMS_TO_TICKS(60 * 1000), LV_TASK_PRIO_MID, this); + systemTask.PushMessage(System::Messages::DisableSleeping); +} + +void Alarm::StopAlerting() { + alarmController.StopAlerting(); + SetSwitchState(LV_ANIM_OFF); + if (taskStopAlarm != nullptr) { + lv_task_del(taskStopAlarm); + taskStopAlarm = nullptr; + } + systemTask.PushMessage(System::Messages::EnableSleeping); + lv_obj_set_hidden(enableSwitch, false); + lv_obj_set_hidden(btnStop, true); +} + +void Alarm::SetSwitchState(lv_anim_enable_t anim) { + switch (alarmController.State()) { + case AlarmController::AlarmState::Set: + lv_switch_on(enableSwitch, anim); + break; + case AlarmController::AlarmState::Not_Set: + lv_switch_off(enableSwitch, anim); + break; + default: + break; + } +} + +void Alarm::ShowInfo() { + btnMessage = lv_btn_create(lv_scr_act(), nullptr); + btnMessage->user_data = this; + lv_obj_set_event_cb(btnMessage, btnEventHandler); + lv_obj_set_height(btnMessage, 200); + lv_obj_set_width(btnMessage, 150); + lv_obj_align(btnMessage, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + txtMessage = lv_label_create(btnMessage, nullptr); + lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY); + + if (alarmController.State() == AlarmController::AlarmState::Set) { + auto timeToAlarm = alarmController.SecondsToAlarm(); + + auto daysToAlarm = timeToAlarm / 86400; + auto hrsToAlarm = (timeToAlarm % 86400) / 3600; + auto minToAlarm = (timeToAlarm % 3600) / 60; + auto secToAlarm = timeToAlarm % 60; + + lv_label_set_text_fmt( + txtMessage, "Time to\nalarm:\n%2lu Days\n%2lu Hours\n%2lu Minutes\n%2lu Seconds", daysToAlarm, hrsToAlarm, minToAlarm, secToAlarm); + } else { + lv_label_set_text(txtMessage, "Alarm\nis not\nset."); + } +} + +void Alarm::HideInfo() { + lv_obj_del(btnMessage); + txtMessage = nullptr; + btnMessage = nullptr; +} + +void Alarm::SetRecurButtonState() { + using Pinetime::Controllers::AlarmController; + switch (alarmController.Recurrence()) { + case AlarmController::RecurType::None: + lv_label_set_text(txtRecur, "ONCE"); + break; + case AlarmController::RecurType::Daily: + lv_label_set_text(txtRecur, "DAILY"); + break; + case AlarmController::RecurType::Weekdays: + lv_label_set_text(txtRecur, "MON-FRI"); + } +} + +void Alarm::ToggleRecurrence() { + using Pinetime::Controllers::AlarmController; + switch (alarmController.Recurrence()) { + case AlarmController::RecurType::None: + alarmController.SetRecurrence(AlarmController::RecurType::Daily); + break; + case AlarmController::RecurType::Daily: + alarmController.SetRecurrence(AlarmController::RecurType::Weekdays); + break; + case AlarmController::RecurType::Weekdays: + alarmController.SetRecurrence(AlarmController::RecurType::None); + } + SetRecurButtonState(); +} diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h new file mode 100644 index 0000000..f74dd68 --- /dev/null +++ b/src/displayapp/screens/Alarm.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2021 mruss77, Florian + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ +#pragma once + +#include "displayapp/screens/Screen.h" +#include "systemtask/SystemTask.h" +#include "displayapp/LittleVgl.h" +#include "components/alarm/AlarmController.h" + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Alarm : public Screen { + public: + Alarm(DisplayApp* app, + Controllers::AlarmController& alarmController, + Pinetime::Controllers::Settings& settingsController, + System::SystemTask& systemTask); + ~Alarm() override; + void SetAlerting(); + void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + void StopAlerting(); + + private: + uint8_t alarmHours; + uint8_t alarmMinutes; + Controllers::AlarmController& alarmController; + Controllers::Settings& settingsController; + System::SystemTask& systemTask; + + lv_obj_t *time, *lblampm, *btnStop, *txtStop, *btnMinutesUp, *btnMinutesDown, *btnHoursUp, *btnHoursDown, *txtMinUp, + *txtMinDown, *txtHrUp, *txtHrDown, *btnRecur, *txtRecur, *btnInfo, *txtInfo, *enableSwitch; + lv_obj_t* txtMessage = nullptr; + lv_obj_t* btnMessage = nullptr; + lv_task_t* taskStopAlarm = nullptr; + + enum class EnableButtonState { On, Off, Alerting }; + void SetRecurButtonState(); + void SetSwitchState(lv_anim_enable_t anim); + void SetAlarm(); + void ShowInfo(); + void HideInfo(); + void ToggleRecurrence(); + void UpdateAlarmTime(); + }; + }; + }; +} diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index b7c8ebd..5daafd1 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -36,7 +36,7 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) { std::unique_ptr<Screen> ApplicationList::CreateScreen1() { std::array<Screens::Tile::Applications, 6> applications {{ - {Symbols::clock}, + {Symbols::clock, Apps::Alarm}, }}; return std::make_unique<Screens::Tile>(0, 1, app, settingsController, batteryController, dateTimeController, applications); |
