diff options
author | Jean-François Milants <jf@codingfield.com> | 2022-09-11 14:59:49 +0200 |
---|---|---|
committer | Jean-François Milants <jf@codingfield.com> | 2022-09-11 14:59:49 +0200 |
commit | ada2c09581d2d13acfa5ce9a97671c0ec17863f1 (patch) | |
tree | 2f776adc59d0c63e403d2043cb8460e65d6c46fe /src/displayapp/screens | |
parent | 18cff286c75f432095db4b188e0f9a8a9e2bd8e8 (diff) | |
parent | c9a5c3fa5c930a5939d3114a6c6b48570d61ca24 (diff) |
Merge branch 'develop' into infineat-external-resources
# Conflicts:
# src/displayapp/screens/Symbols.h
# src/displayapp/screens/settings/SettingWatchFace.cpp
# src/displayapp/screens/settings/SettingWatchFace.h
Diffstat (limited to 'src/displayapp/screens')
54 files changed, 923 insertions, 1187 deletions
diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index c1ee6469..d6371ce6 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -18,10 +18,18 @@ #include "displayapp/screens/Alarm.h" #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; using Pinetime::Controllers::AlarmController; +namespace { + void ValueChangedHandler(void* userData) { + auto* screen = static_cast<Alarm*>(userData); + screen->OnValueChanged(); + } +} + static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast<Alarm*>(obj->user_data); screen->OnButtonEvent(obj, event); @@ -34,58 +42,33 @@ static void StopAlarmTaskCallback(lv_task_t* task) { Alarm::Alarm(DisplayApp* app, Controllers::AlarmController& alarmController, - Pinetime::Controllers::Settings& settingsController, + Controllers::Settings::ClockType clockType, 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_MAKE(0xb0, 0xb0, 0xb0)); - - 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_MAKE(0xb0, 0xb0, 0xb0)); - 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, "-"); + : Screen(app), alarmController {alarmController}, systemTask {systemTask} { + + hourCounter.Create(); + lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); + if (clockType == Controllers::Settings::ClockType::H12) { + hourCounter.EnableTwelveHourMode(); + + 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_label_set_text_static(lblampm, "AM"); + lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 0, 30); + } + hourCounter.SetValue(alarmController.Hours()); + hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + minuteCounter.Create(); + lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + minuteCounter.SetValue(alarmController.Minutes()); + minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + + lv_obj_t* colonLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(colonLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); + lv_label_set_text_static(colonLabel, ":"); + lv_obj_align(colonLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, -29); btnStop = lv_btn_create(lv_scr_act(), nullptr); btnStop->user_data = this; @@ -97,6 +80,8 @@ Alarm::Alarm(DisplayApp* app, lv_label_set_text_static(txtStop, Symbols::stop); lv_obj_set_hidden(btnStop, true); + static constexpr lv_color_t bgColor = Colors::bgAlt; + btnRecur = lv_btn_create(lv_scr_act(), nullptr); btnRecur->user_data = this; lv_obj_set_event_cb(btnRecur, btnEventHandler); @@ -104,13 +89,18 @@ Alarm::Alarm(DisplayApp* app, lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); txtRecur = lv_label_create(btnRecur, nullptr); SetRecurButtonState(); + lv_obj_set_style_local_bg_color(btnRecur, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); 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_obj_set_size(btnInfo, 50, 50); + lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, -4); + lv_obj_set_style_local_bg_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, bgColor); + lv_obj_set_style_local_border_width(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 4); + lv_obj_set_style_local_border_color(btnInfo, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + + lv_obj_t* txtInfo = lv_label_create(btnInfo, nullptr); lv_label_set_text_static(txtInfo, "i"); enableSwitch = lv_switch_create(lv_scr_act(), nullptr); @@ -119,6 +109,7 @@ Alarm::Alarm(DisplayApp* app, 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); + lv_obj_set_style_local_bg_color(enableSwitch, LV_SWITCH_PART_BG, LV_STATE_DEFAULT, bgColor); UpdateAlarmTime(); @@ -136,8 +127,14 @@ Alarm::~Alarm() { lv_obj_clean(lv_scr_act()); } +void Alarm::DisableAlarm() { + if (alarmController.State() == AlarmController::AlarmState::Set) { + alarmController.DisableAlarm(); + lv_switch_off(enableSwitch, LV_ANIM_ON); + } +} + void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { - using Pinetime::Controllers::AlarmController; if (event == LV_EVENT_CLICKED) { if (obj == btnStop) { StopAlerting(); @@ -159,49 +156,8 @@ void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } 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) { + DisableAlarm(); ToggleRecurrence(); } } @@ -224,30 +180,20 @@ bool Alarm::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return alarmController.State() == AlarmController::AlarmState::Alerting && event == TouchEvents::SwipeDown; } +void Alarm::OnValueChanged() { + DisableAlarm(); + UpdateAlarmTime(); +} + 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; + if (lblampm != nullptr) { + if (hourCounter.GetValue() >= 12) { + lv_label_set_text_static(lblampm, "PM"); + } else { + lv_label_set_text_static(lblampm, "AM"); } - } else { - lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes); } - alarmController.SetAlarmTime(alarmHours, alarmMinutes); + alarmController.SetAlarmTime(hourCounter.GetValue(), minuteCounter.GetValue()); } void Alarm::SetAlerting() { @@ -283,6 +229,9 @@ void Alarm::SetSwitchState(lv_anim_enable_t anim) { } void Alarm::ShowInfo() { + if (btnMessage != nullptr) { + return; + } btnMessage = lv_btn_create(lv_scr_act(), nullptr); btnMessage->user_data = this; lv_obj_set_event_cb(btnMessage, btnEventHandler); diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h index 80e446f1..fba9d5d9 100644 --- a/src/displayapp/screens/Alarm.h +++ b/src/displayapp/screens/Alarm.h @@ -21,6 +21,7 @@ #include "systemtask/SystemTask.h" #include "displayapp/LittleVgl.h" #include "components/alarm/AlarmController.h" +#include "displayapp/widgets/Counter.h" namespace Pinetime { namespace Applications { @@ -29,29 +30,28 @@ namespace Pinetime { public: Alarm(DisplayApp* app, Controllers::AlarmController& alarmController, - Pinetime::Controllers::Settings& settingsController, + Controllers::Settings::ClockType clockType, 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 OnValueChanged(); 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 *btnStop, *txtStop, *btnRecur, *txtRecur, *btnInfo, *enableSwitch; + lv_obj_t* lblampm = nullptr; lv_obj_t* txtMessage = nullptr; lv_obj_t* btnMessage = nullptr; lv_task_t* taskStopAlarm = nullptr; enum class EnableButtonState { On, Off, Alerting }; + void DisableAlarm(); void SetRecurButtonState(); void SetSwitchState(lv_anim_enable_t anim); void SetAlarm(); @@ -59,6 +59,8 @@ namespace Pinetime { void HideInfo(); void ToggleRecurrence(); void UpdateAlarmTime(); + Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_76); + Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); }; }; }; diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 9798a861..9f3e9568 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -1,33 +1,34 @@ #include "displayapp/screens/ApplicationList.h" #include <lvgl/lvgl.h> -#include <array> -#include "displayapp/screens/Symbols.h" -#include "displayapp/screens/Tile.h" +#include <functional> #include "displayapp/Apps.h" #include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; +constexpr std::array<Tile::Applications, ApplicationList::applications.size()> ApplicationList::applications; + +auto ApplicationList::CreateScreenList() const { + std::array<std::function<std::unique_ptr<Screen>()>, nScreens> screens; + for (size_t i = 0; i < screens.size(); i++) { + screens[i] = [this, i]() -> std::unique_ptr<Screen> { + return CreateScreen(i); + }; + } + return screens; +} + ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController, Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::Ble& bleController, Controllers::DateTime& dateTimeController) : Screen(app), settingsController {settingsController}, batteryController {batteryController}, + bleController {bleController}, dateTimeController {dateTimeController}, - screens {app, - settingsController.GetAppMenu(), - { - [this]() -> std::unique_ptr<Screen> { - return CreateScreen1(); - }, - [this]() -> std::unique_ptr<Screen> { - return CreateScreen2(); - }, - //[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); } - }, - Screens::ScreenListModes::UpDown} { + screens {app, settingsController.GetAppMenu(), CreateScreenList(), Screens::ScreenListModes::UpDown} { } ApplicationList::~ApplicationList() { @@ -38,42 +39,18 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return screens.OnTouchEvent(event); } -std::unique_ptr<Screen> ApplicationList::CreateScreen1() { - std::array<Screens::Tile::Applications, 6> applications {{ - {Symbols::stopWatch, Apps::StopWatch}, - {Symbols::clock, Apps::Alarm}, - {Symbols::hourGlass, Apps::Timer}, - {Symbols::shoe, Apps::Steps}, - {Symbols::heartBeat, Apps::HeartRate}, - {Symbols::music, Apps::Music}, - }}; - - return std::make_unique<Screens::Tile>(0, 2, app, settingsController, batteryController, dateTimeController, applications); +std::unique_ptr<Screen> ApplicationList::CreateScreen(unsigned int screenNum) const { + std::array<Tile::Applications, appsPerScreen> apps; + for (int i = 0; i < appsPerScreen; i++) { + apps[i] = applications[screenNum * appsPerScreen + i]; + } + + return std::make_unique<Screens::Tile>(screenNum, + nScreens, + app, + settingsController, + batteryController, + bleController, + dateTimeController, + apps); } - -std::unique_ptr<Screen> ApplicationList::CreateScreen2() { - std::array<Screens::Tile::Applications, 6> applications {{ - {Symbols::paintbrush, Apps::Paint}, - {Symbols::paddle, Apps::Paddle}, - {"2", Apps::Twos}, - {Symbols::chartLine, Apps::Motion}, - {Symbols::drum, Apps::Metronome}, - {Symbols::map, Apps::Navigation}, - }}; - - return std::make_unique<Screens::Tile>(1, 2, app, settingsController, batteryController, dateTimeController, applications); -} - -/*std::unique_ptr<Screen> ApplicationList::CreateScreen3() { - std::array<Screens::Tile::Applications, 6> applications { - {{"A", Apps::Meter}, - {"B", Apps::Navigation}, - {"C", Apps::Clock}, - {"D", Apps::Music}, - {"E", Apps::SysInfo}, - {"F", Apps::Brightness} - } - }; - - return std::make_unique<Screens::Tile>(2, 3, app, settingsController, batteryController, dateTimeController, applications); -}*/ diff --git a/src/displayapp/screens/ApplicationList.h b/src/displayapp/screens/ApplicationList.h index f430a89e..e7c094bf 100644 --- a/src/displayapp/screens/ApplicationList.h +++ b/src/displayapp/screens/ApplicationList.h @@ -1,5 +1,6 @@ #pragma once +#include <array> #include <memory> #include "displayapp/screens/Screen.h" @@ -7,6 +8,8 @@ #include "components/datetime/DateTimeController.h" #include "components/settings/Settings.h" #include "components/battery/BatteryController.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/Tile.h" namespace Pinetime { namespace Applications { @@ -16,19 +19,41 @@ namespace Pinetime { explicit ApplicationList(DisplayApp* app, Pinetime::Controllers::Settings& settingsController, Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::Ble& bleController, Controllers::DateTime& dateTimeController); ~ApplicationList() override; bool OnTouchEvent(TouchEvents event) override; private: + auto CreateScreenList() const; + std::unique_ptr<Screen> CreateScreen(unsigned int screenNum) const; + Controllers::Settings& settingsController; Pinetime::Controllers::Battery& batteryController; + Pinetime::Controllers::Ble& bleController; Controllers::DateTime& dateTimeController; - ScreenList<2> screens; - std::unique_ptr<Screen> CreateScreen1(); - std::unique_ptr<Screen> CreateScreen2(); - // std::unique_ptr<Screen> CreateScreen3(); + static constexpr int appsPerScreen = 6; + + // Increment this when more space is needed + static constexpr int nScreens = 2; + + static constexpr std::array<Tile::Applications, appsPerScreen * nScreens> applications {{ + {Symbols::stopWatch, Apps::StopWatch}, + {Symbols::clock, Apps::Alarm}, + {Symbols::hourGlass, Apps::Timer}, + {Symbols::shoe, Apps::Steps}, + {Symbols::heartBeat, Apps::HeartRate}, + {Symbols::music, Apps::Music}, + + {Symbols::paintbrush, Apps::Paint}, + {Symbols::paddle, Apps::Paddle}, + {"2", Apps::Twos}, + {Symbols::chartLine, Apps::Motion}, + {Symbols::drum, Apps::Metronome}, + {Symbols::map, Apps::Navigation}, + }}; + ScreenList<nScreens> screens; }; } } diff --git a/src/displayapp/screens/BatteryInfo.cpp b/src/displayapp/screens/BatteryInfo.cpp index d9d479f8..9febda61 100644 --- a/src/displayapp/screens/BatteryInfo.cpp +++ b/src/displayapp/screens/BatteryInfo.cpp @@ -1,6 +1,7 @@ #include "displayapp/screens/BatteryInfo.h" #include "displayapp/DisplayApp.h" #include "components/battery/BatteryController.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -16,9 +17,9 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont lv_obj_align(charging_bar, nullptr, LV_ALIGN_CENTER, 0, 10); lv_bar_set_anim_time(charging_bar, 1000); lv_obj_set_style_local_radius(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, lv_color_hex(0x222222)); + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_opa(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100); - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0xFF0000)); + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED); lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON); status = lv_label_create(lv_scr_act(), nullptr); @@ -33,7 +34,7 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont lv_obj_align(percent, nullptr, LV_ALIGN_CENTER, 0, -60); voltage = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(voltage, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xff, 0xb0, 0x0)); + lv_obj_set_style_local_text_color(voltage, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltage / 1000, batteryVoltage % 1000 / 10); lv_label_set_align(voltage, LV_LABEL_ALIGN_CENTER); lv_obj_align(voltage, nullptr, LV_ALIGN_CENTER, 0, 95); @@ -62,7 +63,7 @@ void BatteryInfo::Refresh() { lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW); lv_label_set_text_static(status, "Battery low"); } else { - lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::highlight); lv_label_set_text_static(status, "Discharging"); } diff --git a/src/displayapp/screens/FirmwareValidation.cpp b/src/displayapp/screens/FirmwareValidation.cpp index a3c97616..a2314690 100644 --- a/src/displayapp/screens/FirmwareValidation.cpp +++ b/src/displayapp/screens/FirmwareValidation.cpp @@ -3,6 +3,7 @@ #include "Version.h" #include "components/firmwarevalidator/FirmwareValidator.h" #include "displayapp/DisplayApp.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -42,7 +43,7 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app, lv_obj_set_size(buttonValidate, 115, 50); lv_obj_align(buttonValidate, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_set_event_cb(buttonValidate, ButtonEventHandler); - lv_obj_set_style_local_bg_color(buttonValidate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_bg_color(buttonValidate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); labelButtonValidate = lv_label_create(buttonValidate, nullptr); lv_label_set_text_static(labelButtonValidate, "Validate"); @@ -51,7 +52,7 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app, buttonReset->user_data = this; lv_obj_set_size(buttonReset, 115, 50); lv_obj_align(buttonReset, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); - lv_obj_set_style_local_bg_color(buttonReset, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0x0, 0x0)); + lv_obj_set_style_local_bg_color(buttonReset, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); lv_obj_set_event_cb(buttonReset, ButtonEventHandler); labelButtonReset = lv_label_create(buttonReset, nullptr); diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp index 2a1884f6..e06b59b5 100644 --- a/src/displayapp/screens/FlashLight.cpp +++ b/src/displayapp/screens/FlashLight.cpp @@ -1,37 +1,35 @@ #include "displayapp/screens/FlashLight.h" #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; namespace { - void event_handler(lv_obj_t* obj, lv_event_t event) { - auto* screen = static_cast<FlashLight*>(obj->user_data); - screen->OnClickEvent(obj, event); + void EventHandler(lv_obj_t* obj, lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + auto* screen = static_cast<FlashLight*>(obj->user_data); + screen->Toggle(); + } } } FlashLight::FlashLight(Pinetime::Applications::DisplayApp* app, System::SystemTask& systemTask, Controllers::BrightnessController& brightnessController) - : Screen(app), - systemTask {systemTask}, - brightnessController {brightnessController} - -{ - brightnessController.Backup(); + : Screen(app), systemTask {systemTask}, brightnessController {brightnessController} { - brightnessLevel = brightnessController.Level(); + brightnessController.Set(Controllers::BrightnessController::Levels::Low); flashLight = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); - lv_label_set_text_static(flashLight, Symbols::highlight); + lv_label_set_text_static(flashLight, Symbols::flashlight); lv_obj_align(flashLight, nullptr, LV_ALIGN_CENTER, 0, 0); - for (auto& i : indicators) { - i = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_size(i, 15, 10); - lv_obj_set_style_local_border_width(i, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 2); + for (auto& indicator : indicators) { + indicator = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(indicator, 15, 10); + lv_obj_set_style_local_border_width(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 2); } lv_obj_align(indicators[1], flashLight, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); @@ -48,7 +46,7 @@ FlashLight::FlashLight(Pinetime::Applications::DisplayApp* app, lv_label_set_text_static(backgroundAction, ""); lv_obj_set_click(backgroundAction, true); backgroundAction->user_data = this; - lv_obj_set_event_cb(backgroundAction, event_handler); + lv_obj_set_event_cb(backgroundAction, EventHandler); systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); } @@ -56,27 +54,19 @@ FlashLight::FlashLight(Pinetime::Applications::DisplayApp* app, FlashLight::~FlashLight() { lv_obj_clean(lv_scr_act()); lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - brightnessController.Restore(); systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); } void FlashLight::SetColors() { - if (isOn) { - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - lv_obj_set_style_local_text_color(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - for (auto& i : indicators) { - lv_obj_set_style_local_bg_color(i, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - lv_obj_set_style_local_bg_color(i, LV_OBJ_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_WHITE); - lv_obj_set_style_local_border_color(i, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - } - } else { - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_obj_set_style_local_text_color(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - for (auto& i : indicators) { - lv_obj_set_style_local_bg_color(i, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - lv_obj_set_style_local_bg_color(i, LV_OBJ_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_BLACK); - lv_obj_set_style_local_border_color(i, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); - } + lv_color_t bgColor = isOn ? LV_COLOR_WHITE : LV_COLOR_BLACK; + lv_color_t fgColor = isOn ? Colors::lightGray : LV_COLOR_WHITE; + + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, bgColor); + lv_obj_set_style_local_text_color(flashLight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, fgColor); + for (auto& indicator : indicators) { + lv_obj_set_style_local_bg_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, fgColor); + lv_obj_set_style_local_bg_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DISABLED, bgColor); + lv_obj_set_style_local_border_color(indicator, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, fgColor); } } @@ -95,37 +85,43 @@ void FlashLight::SetIndicators() { } } -void FlashLight::OnClickEvent(lv_obj_t* obj, lv_event_t event) { - if (obj == backgroundAction && event == LV_EVENT_CLICKED) { - isOn = !isOn; - SetColors(); +void FlashLight::Toggle() { + isOn = !isOn; + SetColors(); + if (isOn) { + brightnessController.Set(brightnessLevel); + } else { + brightnessController.Set(Controllers::BrightnessController::Levels::Low); } } bool FlashLight::OnTouchEvent(Pinetime::Applications::TouchEvents event) { using namespace Pinetime::Controllers; + auto SetState = [this]() { + if (isOn) { + brightnessController.Set(brightnessLevel); + } + SetIndicators(); + }; + if (event == TouchEvents::SwipeLeft) { if (brightnessLevel == BrightnessController::Levels::High) { brightnessLevel = BrightnessController::Levels::Medium; - brightnessController.Set(brightnessLevel); - SetIndicators(); + SetState(); } else if (brightnessLevel == BrightnessController::Levels::Medium) { brightnessLevel = BrightnessController::Levels::Low; - brightnessController.Set(brightnessLevel); - SetIndicators(); + SetState(); } return true; } if (event == TouchEvents::SwipeRight) { if (brightnessLevel == BrightnessController::Levels::Low) { brightnessLevel = BrightnessController::Levels::Medium; - brightnessController.Set(brightnessLevel); - SetIndicators(); + SetState(); } else if (brightnessLevel == BrightnessController::Levels::Medium) { brightnessLevel = BrightnessController::Levels::High; - brightnessController.Set(brightnessLevel); - SetIndicators(); + SetState(); } return true; } diff --git a/src/displayapp/screens/FlashLight.h b/src/displayapp/screens/FlashLight.h index e91a1032..c885048f 100644 --- a/src/displayapp/screens/FlashLight.h +++ b/src/displayapp/screens/FlashLight.h @@ -17,7 +17,7 @@ namespace Pinetime { ~FlashLight() override; bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; - void OnClickEvent(lv_obj_t* obj, lv_event_t event); + void Toggle(); private: void SetIndicators(); @@ -26,7 +26,7 @@ namespace Pinetime { Pinetime::System::SystemTask& systemTask; Controllers::BrightnessController& brightnessController; - Controllers::BrightnessController::Levels brightnessLevel; + Controllers::BrightnessController::Levels brightnessLevel = Controllers::BrightnessController::Levels::High; lv_obj_t* flashLight; lv_obj_t* backgroundAction; diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp index 35e06bbc..305e0c4b 100644 --- a/src/displayapp/screens/HeartRate.cpp +++ b/src/displayapp/screens/HeartRate.cpp @@ -3,6 +3,7 @@ #include <components/heartrate/HeartRateController.h> #include "displayapp/DisplayApp.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -36,10 +37,11 @@ HeartRate::HeartRate(Pinetime::Applications::DisplayApp* app, lv_obj_set_style_local_text_font(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); - if (isHrRunning) - lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); - else - lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + if (isHrRunning) { + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); + } else { + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + } lv_label_set_text_static(label_hr, "000"); lv_obj_align(label_hr, nullptr, LV_ALIGN_CENTER, 0, -40); @@ -97,12 +99,12 @@ void HeartRate::OnStartStopEvent(lv_event_t event) { heartRateController.Start(); UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); - lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); } else { heartRateController.Stop(); UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); - lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); } } } diff --git a/src/displayapp/screens/InfiniPaint.cpp b/src/displayapp/screens/InfiniPaint.cpp index 733b4e27..0b6864e8 100644 --- a/src/displayapp/screens/InfiniPaint.cpp +++ b/src/displayapp/screens/InfiniPaint.cpp @@ -1,6 +1,7 @@ #include "displayapp/screens/InfiniPaint.h" #include "displayapp/DisplayApp.h" #include "displayapp/LittleVgl.h" +#include "displayapp/InfiniTimeTheme.h" #include <algorithm> // std::fill @@ -26,7 +27,7 @@ bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { selectColor = LV_COLOR_MAGENTA; break; case 1: - selectColor = LV_COLOR_MAKE(0x0, 0xb0, 0x0); + selectColor = Colors::green; break; case 2: selectColor = LV_COLOR_WHITE; diff --git a/src/displayapp/screens/Label.cpp b/src/displayapp/screens/Label.cpp index 4486d6fd..d5a09be9 100644 --- a/src/displayapp/screens/Label.cpp +++ b/src/displayapp/screens/Label.cpp @@ -3,34 +3,9 @@ using namespace Pinetime::Applications::Screens; Label::Label(uint8_t screenID, uint8_t numScreens, Pinetime::Applications::DisplayApp* app, lv_obj_t* labelText) - : Screen(app), labelText {labelText} { + : Screen(app), labelText {labelText}, pageIndicator(screenID, numScreens) { - if (numScreens > 1) { - pageIndicatorBasePoints[0].x = LV_HOR_RES - 1; - pageIndicatorBasePoints[0].y = 0; - pageIndicatorBasePoints[1].x = LV_HOR_RES - 1; - pageIndicatorBasePoints[1].y = LV_VER_RES; - - pageIndicatorBase = lv_line_create(lv_scr_act(), NULL); - lv_obj_set_style_local_line_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_color(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); - lv_obj_set_style_local_line_rounded(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true); - lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2); - - uint16_t indicatorSize = LV_VER_RES / numScreens; - uint16_t indicatorPos = indicatorSize * screenID; - - pageIndicatorPoints[0].x = LV_HOR_RES - 1; - pageIndicatorPoints[0].y = indicatorPos; - pageIndicatorPoints[1].x = LV_HOR_RES - 1; - pageIndicatorPoints[1].y = indicatorPos + indicatorSize; - - pageIndicator = lv_line_create(lv_scr_act(), NULL); - lv_obj_set_style_local_line_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - lv_obj_set_style_local_line_rounded(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true); - lv_line_set_points(pageIndicator, pageIndicatorPoints, 2); - } + pageIndicator.Create(); } Label::~Label() { diff --git a/src/displayapp/screens/Label.h b/src/displayapp/screens/Label.h index 3fe5111f..acd8b377 100644 --- a/src/displayapp/screens/Label.h +++ b/src/displayapp/screens/Label.h @@ -1,6 +1,7 @@ #pragma once #include "displayapp/screens/Screen.h" +#include "displayapp/widgets/PageIndicator.h" #include <lvgl/lvgl.h> namespace Pinetime { @@ -14,10 +15,7 @@ namespace Pinetime { private: lv_obj_t* labelText = nullptr; - lv_point_t pageIndicatorBasePoints[2]; - lv_point_t pageIndicatorPoints[2]; - lv_obj_t* pageIndicatorBase; - lv_obj_t* pageIndicator; + Widgets::PageIndicator pageIndicator; }; } } diff --git a/src/displayapp/screens/List.cpp b/src/displayapp/screens/List.cpp index 0bc7da80..f44825c7 100644 --- a/src/displayapp/screens/List.cpp +++ b/src/displayapp/screens/List.cpp @@ -16,37 +16,14 @@ List::List(uint8_t screenID, DisplayApp* app, Controllers::Settings& settingsController, std::array<Applications, MAXLISTITEMS>& applications) - : Screen(app), settingsController {settingsController} { + : Screen(app), settingsController {settingsController}, pageIndicator(screenID, numScreens) { // Set the background to Black lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, lv_color_make(0, 0, 0)); settingsController.SetSettingsMenu(screenID); - if (numScreens > 1) { - pageIndicatorBasePoints[0].x = LV_HOR_RES - 1; - pageIndicatorBasePoints[0].y = 0; - pageIndicatorBasePoints[1].x = LV_HOR_RES - 1; - pageIndicatorBasePoints[1].y = LV_VER_RES; - - pageIndicatorBase = lv_line_create(lv_scr_act(), NULL); - lv_obj_set_style_local_line_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_color(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); - lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2); - - const uint16_t indicatorSize = LV_VER_RES / numScreens; - const uint16_t indicatorPos = indicatorSize * screenID; - - pageIndicatorPoints[0].x = LV_HOR_RES - 1; - pageIndicatorPoints[0].y = indicatorPos; - pageIndicatorPoints[1].x = LV_HOR_RES - 1; - pageIndicatorPoints[1].y = indicatorPos + indicatorSize; - - pageIndicator = lv_line_create(lv_scr_act(), NULL); - lv_obj_set_style_local_line_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - lv_line_set_points(pageIndicator, pageIndicatorPoints, 2); - } + pageIndicator.Create(); lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); diff --git a/src/displayapp/screens/List.h b/src/displayapp/screens/List.h index 88ef28ea..b5bc032c 100644 --- a/src/displayapp/screens/List.h +++ b/src/displayapp/screens/List.h @@ -4,6 +4,7 @@ #include <cstdint> #include <array> #include "displayapp/screens/Screen.h" +#include "displayapp/widgets/PageIndicator.h" #include "displayapp/Apps.h" #include "components/settings/Settings.h" @@ -35,10 +36,7 @@ namespace Pinetime { lv_obj_t* itemApps[MAXLISTITEMS]; - lv_point_t pageIndicatorBasePoints[2]; - lv_point_t pageIndicatorPoints[2]; - lv_obj_t* pageIndicatorBase; - lv_obj_t* pageIndicator; + Widgets::PageIndicator pageIndicator; }; } } diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp index 2ffc52dd..174ac1b6 100644 --- a/src/displayapp/screens/Metronome.cpp +++ b/src/displayapp/screens/Metronome.cpp @@ -1,5 +1,6 @@ #include "displayapp/screens/Metronome.h" #include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -12,7 +13,7 @@ namespace { lv_obj_t* createLabel(const char* name, lv_obj_t* reference, lv_align_t align, lv_font_t* font, uint8_t x, uint8_t y) { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font); - lv_obj_set_style_local_text_color(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_text_color(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_label_set_text(label, name); lv_obj_align(label, reference, align, x, y); diff --git a/src/displayapp/screens/Motion.cpp b/src/displayapp/screens/Motion.cpp index f7ffcc7c..c2dc4dac 100644 --- a/src/displayapp/screens/Motion.cpp +++ b/src/displayapp/screens/Motion.cpp @@ -1,6 +1,7 @@ #include "displayapp/screens/Motion.h" #include <lvgl/lvgl.h> #include "displayapp/DisplayApp.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -19,7 +20,7 @@ Motion::Motion(Pinetime::Applications::DisplayApp* app, Controllers::MotionContr /*Add 3 data series*/ ser1 = lv_chart_add_series(chart, LV_COLOR_RED); - ser2 = lv_chart_add_series(chart, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + ser2 = lv_chart_add_series(chart, Colors::green); ser3 = lv_chart_add_series(chart, LV_COLOR_YELLOW); lv_chart_init_points(chart, ser1, 0); diff --git a/src/displayapp/screens/Navigation.cpp b/src/displayapp/screens/Navigation.cpp index 5779df3a..f6389734 100644 --- a/src/displayapp/screens/Navigation.cpp +++ b/src/displayapp/screens/Navigation.cpp @@ -19,6 +19,7 @@ #include <cstdint> #include "displayapp/DisplayApp.h" #include "components/ble/NavigationService.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -192,7 +193,7 @@ void Navigation::Refresh() { if (progress > 90) { lv_obj_set_style_local_bg_color(barProgress, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED); } else { - lv_obj_set_style_local_bg_color(barProgress, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xff, 0xb0, 0x0)); + lv_obj_set_style_local_bg_color(barProgress, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::orange); } } } diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index d7fe93a0..90a010f5 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -3,6 +3,8 @@ #include "components/ble/MusicService.h" #include "components/ble/AlertNotificationService.h" #include "displayapp/screens/Symbols.h" +#include <algorithm> +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; extern lv_font_t jetbrains_mono_extrabold_compressed; @@ -20,30 +22,23 @@ Notifications::Notifications(DisplayApp* app, motorController {motorController}, systemTask {systemTask}, mode {mode} { + notificationManager.ClearNewNotificationFlag(); auto notification = notificationManager.GetLastNotification(); if (notification.valid) { currentId = notification.id; currentItem = std::make_unique<NotificationItem>(notification.Title(), notification.Message(), - notification.index, + 1, notification.category, notificationManager.NbNotifications(), - mode, alertNotificationService, motorController); validDisplay = true; } else { - currentItem = std::make_unique<NotificationItem>("Notification", - "No notification to display", - 0, - notification.category, - notificationManager.NbNotifications(), - Modes::Preview, - alertNotificationService, - motorController); + currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController); + validDisplay = false; } - if (mode == Modes::Preview) { systemTask.PushMessage(System::Messages::DisableSleeping); if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) { @@ -77,7 +72,7 @@ Notifications::~Notifications() { void Notifications::Refresh() { if (mode == Modes::Preview && timeoutLine != nullptr) { TickType_t tick = xTaskGetTickCount(); - int32_t pos = 240 - ((tick - timeoutTickCountStart) / (timeoutLength / 240)); + int32_t pos = LV_HOR_RES - ((tick - timeoutTickCountStart) / (timeoutLength / LV_HOR_RES)); if (pos <= 0) { running = false; } else { @@ -85,6 +80,40 @@ void Notifications::Refresh() { lv_line_set_points(timeoutLine, timeoutLinePoints, 2); } } + + if (dismissingNotification) { + dismissingNotification = false; + auto notification = notificationManager.Get(currentId); + if (!notification.valid) { + notification = notificationManager.GetLastNotification(); + } + currentId = notification.id; + + if (!notification.valid) { + validDisplay = false; + } + + currentItem.reset(nullptr); + if (afterDismissNextMessageFromAbove) { + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); + } else { + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up); + } + + if (validDisplay) { + Controllers::NotificationManager::Notification::Idx currentIdx = notificationManager.IndexOf(currentId); + currentItem = std::make_unique<NotificationItem>(notification.Title(), + notification.Message(), + currentIdx + 1, + notification.category, + notificationManager.NbNotifications(), + alertNotificationService, + motorController); + } else { + currentItem = std::make_unique<NotificationItem>(alertNotificationService, motorController); + } + } + running = currentItem->IsRunning() && running; } @@ -108,52 +137,84 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } switch (event) { + case Pinetime::Applications::TouchEvents::SwipeRight: + if (validDisplay) { + Controllers::NotificationManager::Notification previousNotification; + auto previousMessage = notificationManager.GetPrevious(currentId); + auto nextMessage = notificationManager.GetNext(currentId); + if (!previousMessage.valid) { + // dismissed last message (like 5/5), need to go one message down (like 4/4) + afterDismissNextMessageFromAbove = false; // show next message coming from below + } else { + afterDismissNextMessageFromAbove = true; // show next message coming from above + } + notificationManager.Dismiss(currentId); + if (previousMessage.valid) { + currentId = previousMessage.id; + } else if (nextMessage.valid) { + currentId = nextMessage.id; + } else { + // don't update id, won't be found be refresh and try to load latest message or no message box + } + currentItem.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::RightAnim); + // create black transition screen to let the notification dismiss to blackness + lv_obj_t* blackBox = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(blackBox, LV_HOR_RES, LV_VER_RES); + lv_obj_set_style_local_bg_color(blackBox, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + dismissingNotification = true; + return true; + } + return false; case Pinetime::Applications::TouchEvents::SwipeDown: { Controllers::NotificationManager::Notification previousNotification; - if (validDisplay) + if (validDisplay) { previousNotification = notificationManager.GetPrevious(currentId); - else + } else { previousNotification = notificationManager.GetLastNotification(); + } - if (!previousNotification.valid) + if (!previousNotification.valid) { return true; + } - validDisplay = true; currentId = previousNotification.id; + Controllers::NotificationManager::Notification::Idx currentIdx = notificationManager.IndexOf(currentId); + validDisplay = true; currentItem.reset(nullptr); app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); currentItem = std::make_unique<NotificationItem>(previousNotification.Title(), previousNotification.Message(), - previousNotification.index, + currentIdx + 1, previousNotification.category, notificationManager.NbNotifications(), - mode, alertNotificationService, motorController); } return true; case Pinetime::Applications::TouchEvents::SwipeUp: { Controllers::NotificationManager::Notification nextNotification; - if (validDisplay) + if (validDisplay) { nextNotification = notificationManager.GetNext(currentId); - else + } else { nextNotification = notificationManager.GetLastNotification(); + } if (!nextNotification.valid) { running = false; return false; } - validDisplay = true; currentId = nextNotification.id; + Controllers::NotificationManager::Notification::Idx currentIdx = notificationManager.IndexOf(currentId); + validDisplay = true; currentItem.reset(nullptr); app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up); currentItem = std::make_unique<NotificationItem>(nextNotification.Title(), nextNotification.Message(), - nextNotification.index, + currentIdx + 1, nextNotification.category, notificationManager.NbNotifications(), - mode, alertNotificationService, motorController); } @@ -170,34 +231,49 @@ namespace { } } +Notifications::NotificationItem::NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::MotorController& motorController) + : NotificationItem("Notification", + "No notification to display", + 0, + Controllers::NotificationManager::Categories::Unknown, + 0, + alertNotificationService, + motorController) { +} + Notifications::NotificationItem::NotificationItem(const char* title, const char* msg, uint8_t notifNr, Controllers::NotificationManager::Categories category, uint8_t notifNb, - Modes mode, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController) - : mode {mode}, alertNotificationService {alertNotificationService}, motorController {motorController} { - lv_obj_t* container1 = lv_cont_create(lv_scr_act(), NULL); - - lv_obj_set_style_local_bg_color(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x38, 0x38, 0x38)); - lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10); - lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5); - lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); - - lv_obj_set_pos(container1, 0, 50); - lv_obj_set_size(container1, LV_HOR_RES, 190); - - lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); - lv_cont_set_fit(container1, LV_FIT_NONE); - - lv_obj_t* alert_count = lv_label_create(lv_scr_act(), nullptr); + : alertNotificationService {alertNotificationService}, motorController {motorController} { + container = lv_cont_create(lv_scr_act(), nullptr); + lv_obj_set_size(container, LV_HOR_RES, LV_VER_RES); + lv_obj_set_style_local_bg_color(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_obj_set_style_local_pad_all(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_pad_inner(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_border_width(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + + subject_container = lv_cont_create(container, nullptr); + lv_obj_set_style_local_bg_color(subject_container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_pad_all(subject_container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10); + lv_obj_set_style_local_pad_inner(subject_container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5); + lv_obj_set_style_local_border_width(subject_container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + + lv_obj_set_pos(subject_container, 0, 50); + lv_obj_set_size(subject_container, LV_HOR_RES, LV_VER_RES - 50); + lv_cont_set_layout(subject_container, LV_LAYOUT_COLUMN_LEFT); + lv_cont_set_fit(subject_container, LV_FIT_NONE); + + lv_obj_t* alert_count = lv_label_create(container, nullptr); lv_label_set_text_fmt(alert_count, "%i/%i", notifNr, notifNb); lv_obj_align(alert_count, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 16); - lv_obj_t* alert_type = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(alert_type, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_t* alert_type = lv_label_create(container, nullptr); + lv_obj_set_style_local_text_color(alert_type, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); if (title == nullptr) { lv_label_set_text_static(alert_type, "Notification"); } else { @@ -214,39 +290,34 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_obj_set_width(alert_type, 180); lv_obj_align(alert_type, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 16); - ///////// + lv_obj_t* alert_subject = lv_label_create(subject_container, nullptr); + lv_label_set_long_mode(alert_subject, LV_LABEL_LONG_BREAK); + lv_obj_set_width(alert_subject, LV_HOR_RES - 20); + switch (category) { - default: { - lv_obj_t* alert_subject = lv_label_create(container1, nullptr); - lv_obj_set_style_local_text_color(alert_subject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xff, 0xb0, 0x0)); - lv_label_set_long_mode(alert_subject, LV_LABEL_LONG_BREAK); - lv_obj_set_width(alert_subject, LV_HOR_RES - 20); + default: lv_label_set_text(alert_subject, msg); - } break; + break; case Controllers::NotificationManager::Categories::IncomingCall: { - lv_obj_set_height(container1, 108); - lv_obj_t* alert_subject = lv_label_create(container1, nullptr); - lv_obj_set_style_local_text_color(alert_subject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xff, 0xb0, 0x0)); - lv_label_set_long_mode(alert_subject, LV_LABEL_LONG_BREAK); - lv_obj_set_width(alert_subject, LV_HOR_RES - 20); + lv_obj_set_height(subject_container, 108); lv_label_set_text_static(alert_subject, "Incoming call from"); - lv_obj_t* alert_caller = lv_label_create(container1, nullptr); + lv_obj_t* alert_caller = lv_label_create(subject_container, nullptr); lv_obj_align(alert_caller, alert_subject, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); lv_label_set_long_mode(alert_caller, LV_LABEL_LONG_BREAK); lv_obj_set_width(alert_caller, LV_HOR_RES - 20); lv_label_set_text(alert_caller, msg); - bt_accept = lv_btn_create(lv_scr_act(), nullptr); + bt_accept = lv_btn_create(container, nullptr); bt_accept->user_data = this; lv_obj_set_event_cb(bt_accept, CallEventHandler); lv_obj_set_size(bt_accept, 76, 76); lv_obj_align(bt_accept, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); label_accept = lv_label_create(bt_accept, nullptr); lv_label_set_text_static(label_accept, Symbols::phone); - lv_obj_set_style_local_bg_color(bt_accept, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_bg_color(bt_accept, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); - bt_reject = lv_btn_create(lv_scr_act(), nullptr); + bt_reject = lv_btn_create(container, nullptr); bt_reject->user_data = this; lv_obj_set_event_cb(bt_reject, CallEventHandler); lv_obj_set_size(bt_reject, 76, 76); @@ -255,14 +326,14 @@ Notifications::NotificationItem::NotificationItem(const char* title, lv_label_set_text_static(label_reject, Symbols::phoneSlash); lv_obj_set_style_local_bg_color(bt_reject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED); - bt_mute = lv_btn_create(lv_scr_act(), nullptr); + bt_mute = lv_btn_create(container, nullptr); bt_mute->user_data = this; lv_obj_set_event_cb(bt_mute, CallEventHandler); lv_obj_set_size(bt_mute, 76, 76); lv_obj_align(bt_mute, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); label_mute = lv_label_create(bt_mute, nullptr); lv_label_set_text_static(label_mute, Symbols::volumMute); - lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); } break; } } diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 74160356..9d843a9b 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -33,12 +33,13 @@ namespace Pinetime { class NotificationItem { public: + NotificationItem(Pinetime::Controllers::AlertNotificationService& alertNotificationService, + Pinetime::Controllers::MotorController& motorController); NotificationItem(const char* title, const char* msg, uint8_t notifNr, Controllers::NotificationManager::Categories, uint8_t notifNb, - Modes mode, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController); ~NotificationItem(); @@ -48,16 +49,17 @@ namespace Pinetime { void OnCallButtonEvent(lv_obj_t*, lv_event_t event); private: - lv_obj_t* container1; + lv_obj_t* container; + lv_obj_t* subject_container; lv_obj_t* bt_accept; lv_obj_t* bt_mute; lv_obj_t* bt_reject; lv_obj_t* label_accept; lv_obj_t* label_mute; lv_obj_t* label_reject; - Modes mode; Pinetime::Controllers::AlertNotificationService& alertNotificationService; Pinetime::Controllers::MotorController& motorController; + bool running = true; }; @@ -68,15 +70,19 @@ namespace Pinetime { System::SystemTask& systemTask; Modes mode = Modes::Normal; std::unique_ptr<NotificationItem> currentItem; - Controllers::NotificationManager::Notification::Id currentId; + Pinetime::Controllers::NotificationManager::Notification::Id currentId; bool validDisplay = false; + bool afterDismissNextMessageFromAbove = false; lv_point_t timeoutLinePoints[2] {{0, 1}, {239, 1}}; lv_obj_t* timeoutLine = nullptr; TickType_t timeoutTickCountStart; + static const TickType_t timeoutLength = pdMS_TO_TICKS(7000); bool interacted = true; + bool dismissingNotification = false; + lv_task_t* taskRefresh; }; } diff --git a/src/displayapp/screens/PassKey.cpp b/src/displayapp/screens/PassKey.cpp index 4057a7eb..5d255e44 100644 --- a/src/displayapp/screens/PassKey.cpp +++ b/src/displayapp/screens/PassKey.cpp @@ -5,7 +5,7 @@ using namespace Pinetime::Applications::Screens; PassKey::PassKey(Pinetime::Applications::DisplayApp* app, uint32_t key) : Screen(app) { passkeyLabel = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00)); + lv_obj_set_style_local_text_color(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); lv_obj_set_style_local_text_font(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(passkeyLabel, "%06u", key); lv_obj_align(passkeyLabel, nullptr, LV_ALIGN_CENTER, 0, -20); diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index 0dcdcf59..10ccf1aa 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -20,7 +20,7 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_style_local_bg_opa(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_0); lv_obj_set_style_local_border_width(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 2); lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0); - lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); + lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE); lv_arc_set_end_angle(stepsArc, 200); lv_obj_set_size(stepsArc, 240, 240); lv_arc_set_range(stepsArc, 0, 500); @@ -32,7 +32,7 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); lSteps = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); + lv_obj_set_style_local_text_color(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME); lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index d0db59c0..c68cd854 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -1,10 +1,7 @@ #include "displayapp/screens/StopWatch.h" -#include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" -#include <lvgl/lvgl.h> -#include <FreeRTOS.h> -#include <task.h> +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -30,25 +27,17 @@ namespace { } } -StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) - : Screen(app), - systemTask {systemTask}, - currentState {States::Init}, - startTime {}, - oldTimeElapsed {}, - currentTimeSeparated {}, - lapBuffer {}, - lapNr {} { +StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) : Screen(app), 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_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_label_set_text_static(time, "00:00"); lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -45); msecTime = lv_label_create(lv_scr_act(), nullptr); // lv_obj_set_style_local_text_font(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_label_set_text_static(msecTime, "00"); lv_obj_align(msecTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 3); @@ -65,24 +54,15 @@ StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler); lv_obj_set_size(btnStopLap, 115, 50); lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); - lv_obj_set_style_local_bg_color(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_MAKE(0x18, 0x18, 0x18)); txtStopLap = lv_label_create(btnStopLap, nullptr); - lv_obj_set_style_local_text_color(txtStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); lv_label_set_text_static(txtStopLap, Symbols::stop); lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); - lapOneText = lv_label_create(lv_scr_act(), nullptr); - // lv_obj_set_style_local_text_font(lapOneText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - lv_obj_set_style_local_text_color(lapOneText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_obj_align(lapOneText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 30); - lv_label_set_text_static(lapOneText, ""); - - lapTwoText = lv_label_create(lv_scr_act(), nullptr); - // lv_obj_set_style_local_text_font(lapTwoText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20); - lv_obj_set_style_local_text_color(lapTwoText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_obj_align(lapTwoText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 55); - lv_label_set_text_static(lapTwoText, ""); + lapText = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(lapText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_obj_align(lapText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 30); + lv_label_set_text_static(lapText, ""); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); } @@ -96,16 +76,14 @@ StopWatch::~StopWatch() { void StopWatch::Reset() { currentState = States::Init; oldTimeElapsed = 0; - lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_label_set_text_static(time, "00:00"); lv_label_set_text_static(msecTime, "00"); - lv_label_set_text_static(lapOneText, ""); - lv_label_set_text_static(lapTwoText, ""); - lapBuffer.clearBuffer(); - lapNr = 0; + lv_label_set_text_static(lapText, ""); + lapsDone = 0; lv_obj_set_state(btnStopLap, LV_STATE_DISABLED); lv_obj_set_state(txtStopLap, LV_STATE_DISABLED); } @@ -113,8 +91,8 @@ void StopWatch::Reset() { void StopWatch::Start() { lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT); lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT); - lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::highlight); lv_label_set_text_static(txtPlayPause, Symbols::pause); lv_label_set_text_static(txtStopLap, Symbols::lapsFlag); startTime = xTaskGetTickCount(); @@ -125,7 +103,7 @@ void StopWatch::Start() { void StopWatch::Pause() { startTime = 0; // Store the current time elapsed in cache - oldTimeElapsed += timeElapsed; + oldTimeElapsed = laps[lapsDone]; currentState = States::Halted; lv_label_set_text_static(txtPlayPause, Symbols::play); lv_label_set_text_static(txtStopLap, Symbols::stop); @@ -136,9 +114,9 @@ void StopWatch::Pause() { void StopWatch::Refresh() { if (currentState == States::Running) { - timeElapsed = xTaskGetTickCount() - startTime; - currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed)); + laps[lapsDone] = oldTimeElapsed + xTaskGetTickCount() - startTime; + TimeSeparated_t currentTimeSeparated = convertTicksToTimeSegments(laps[lapsDone]); lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs); lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); } @@ -163,18 +141,17 @@ void StopWatch::stopLapBtnEventHandler(lv_event_t event) { } // If running, then this button is used to save laps if (currentState == States::Running) { - lapBuffer.addLaps(currentTimeSeparated); - lapNr++; - if (lapBuffer[1]) { - lv_label_set_text_fmt(lapOneText, - "#%2d %2d:%02d.%02d", - (lapNr - 1), - lapBuffer[1]->mins, - lapBuffer[1]->secs, - lapBuffer[1]->hundredths); - } - if (lapBuffer[0]) { - lv_label_set_text_fmt(lapTwoText, "#%2d %2d:%02d.%02d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->hundredths); + lv_label_set_text(lapText, ""); + lapsDone = std::min(lapsDone + 1, maxLapCount); + for (int i = lapsDone - displayedLaps; i < lapsDone; i++) { + if (i < 0) { + lv_label_ins_text(lapText, LV_LABEL_POS_LAST, "\n"); + continue; + } + TimeSeparated_t times = convertTicksToTimeSegments(laps[i]); + char buffer[16]; + sprintf(buffer, "#%2d %2d:%02d.%02d\n", i + 1, times.mins, times.secs, times.hundredths); + lv_label_ins_text(lapText, LV_LABEL_POS_LAST, buffer); } } else if (currentState == States::Halted) { Reset(); diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index ef55e2d2..f2f57110 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -1,13 +1,11 @@ #pragma once #include "displayapp/screens/Screen.h" -#include "components/datetime/DateTimeController.h" -#include "displayapp/LittleVgl.h" +#include <lvgl/lvgl.h> #include <FreeRTOS.h> #include "portmacro_cmsis.h" -#include <array> #include "systemtask/SystemTask.h" namespace Pinetime::Applications::Screens { @@ -20,46 +18,6 @@ namespace Pinetime::Applications::Screens { int hundredths; }; - // A simple buffer to hold the latest two laps - template <int N> struct LapTextBuffer_t { - LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} { - } - - void addLaps(const TimeSeparated_t& timeVal) { - head++; - head %= capacity; - buffer[head] = timeVal; - - if (currentSize < capacity) { - currentSize++; - } - } - - void clearBuffer() { - buffer = {}; - currentSize = 0; - head = -1; - } - - TimeSeparated_t* operator[](std::size_t idx) { - // Sanity check for out-of-bounds - if (idx >= 0 && idx < capacity) { - if (idx < currentSize) { - // This transformation is to ensure that head is always pointing to index 0. - const auto transformed_idx = (head - idx) % capacity; - return (&buffer[transformed_idx]); - } - } - return nullptr; - } - - private: - std::array<TimeSeparated_t, N> buffer; - uint8_t currentSize; - uint8_t capacity; - int8_t head; - }; - class StopWatch : public Screen { public: StopWatch(DisplayApp* app, System::SystemTask& systemTask); @@ -76,15 +34,15 @@ namespace Pinetime::Applications::Screens { private: Pinetime::System::SystemTask& systemTask; - TickType_t timeElapsed; - States currentState; + States currentState = States::Init; TickType_t startTime; - TickType_t oldTimeElapsed; - TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs - LapTextBuffer_t<2> lapBuffer; - int lapNr = 0; + TickType_t oldTimeElapsed = 0; + static constexpr int maxLapCount = 20; + TickType_t laps[maxLapCount + 1]; + static constexpr int displayedLaps = 2; + int lapsDone = 0; lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; - lv_obj_t *lapOneText, *lapTwoText; + lv_obj_t* lapText; lv_task_t* taskRefresh; }; diff --git a/src/displayapp/screens/Styles.cpp b/src/displayapp/screens/Styles.cpp index bcfd584f..cebdc70c 100644 --- a/src/displayapp/screens/Styles.cpp +++ b/src/displayapp/screens/Styles.cpp @@ -1,8 +1,9 @@ #include "Styles.h" +#include "displayapp/InfiniTimeTheme.h" void Pinetime::Applications::Screens::SetRadioButtonStyle(lv_obj_t* checkbox) { lv_obj_set_style_local_radius(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); lv_obj_set_style_local_border_width(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); - lv_obj_set_style_local_border_color(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_border_color(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, Colors::highlight); lv_obj_set_style_local_bg_color(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); } diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 46396b3f..c7bf1e59 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -37,20 +37,20 @@ namespace Pinetime { static constexpr const char* chartLine = "\xEF\x88\x81"; static constexpr const char* eye = "\xEF\x81\xAE"; static constexpr const char* home = "\xEF\x80\x95"; + static constexpr const char* sleep = "\xEE\xBD\x84"; static constexpr const char* circle = "\xEF\x84\x91"; // lv_font_sys_48.c - static constexpr const char* settings = "\xEE\xA4\x82"; // e902 + static constexpr const char* settings = "\xEE\xA2\xB8"; - static constexpr const char* brightnessHigh = "\xEE\xA4\x84"; // e904 - static constexpr const char* brightnessLow = "\xEE\xA4\x85"; // e905 - static constexpr const char* brightnessMedium = "\xEE\xA4\x86"; // e906 + static constexpr const char* brightnessLow = "\xEE\x8E\xAA"; + static constexpr const char* brightnessMedium = "\xEE\x8E\xAB"; + static constexpr const char* brightnessHigh = "\xEE\x8E\xAC"; - static constexpr const char* notificationsOff = "\xEE\xA4\x8B"; // e90b - static constexpr const char* notificationsOn = "\xEE\xA4\x8C"; // e90c - - static constexpr const char* highlight = "\xEE\xA4\x87"; // e907 + static constexpr const char* notificationsOff = "\xEE\x9F\xB6"; + static constexpr const char* notificationsOn = "\xEE\x9F\xB7"; + static constexpr const char* flashlight = "\xEF\x80\x8B"; } } } diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index e3983d7c..01c35195 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -12,6 +12,7 @@ #include "components/datetime/DateTimeController.h" #include "components/motion/MotionController.h" #include "drivers/Watchdog.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -136,20 +137,25 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() { uptimeSeconds = uptimeSeconds % secondsInAMinute; // TODO handle more than 100 days of uptime +#ifndef TARGET_DEVICE_NAME + #define TARGET_DEVICE_NAME "UNKNOWN" +#endif + lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); lv_label_set_text_fmt(label, - "#808080 Date# %02d/%02d/%04d\n" + "#808080 Date# %04d-%02d-%02d\n" "#808080 Time# %02d:%02d:%02d\n" "#808080 Uptime#\n %02lud %02lu:%02lu:%02lu\n" "#808080 Battery# %d%%/%03imV\n" "#808080 Backlight# %s\n" "#808080 Last reset# %s\n" "#808080 Accel.# %s\n" - "#808080 Touch.# %x.%x.%x\n", - dateTimeController.Day(), - static_cast<uint8_t>(dateTimeController.Month()), + "#808080 Touch.# %x.%x.%x\n" + "#808080 Model# %s", dateTimeController.Year(), + static_cast<uint8_t>(dateTimeController.Month()), + dateTimeController.Day(), dateTimeController.Hours(), dateTimeController.Minutes(), dateTimeController.Seconds(), @@ -164,7 +170,8 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() { ToString(motionController.DeviceType()), touchPanel.GetChipId(), touchPanel.GetVendorId(), - touchPanel.GetFwVersion()); + touchPanel.GetFwVersion(), + TARGET_DEVICE_NAME); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique<Screens::Label>(1, 5, app, label); } @@ -212,7 +219,7 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen4() { lv_table_set_col_cnt(infoTask, 4); lv_table_set_row_cnt(infoTask, maxTaskCount + 1); lv_obj_set_style_local_pad_all(infoTask, LV_TABLE_PART_CELL1, LV_STATE_DEFAULT, 0); - lv_obj_set_style_local_border_color(infoTask, LV_TABLE_PART_CELL1, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); + lv_obj_set_style_local_border_color(infoTask, LV_TABLE_PART_CELL1, LV_STATE_DEFAULT, Colors::lightGray); lv_table_set_cell_value(infoTask, 0, 0, "#"); lv_table_set_col_width(infoTask, 0, 30); diff --git a/src/displayapp/screens/Tile.cpp b/src/displayapp/screens/Tile.cpp index cce1d2ed..a60076ed 100644 --- a/src/displayapp/screens/Tile.cpp +++ b/src/displayapp/screens/Tile.cpp @@ -1,6 +1,8 @@ #include "displayapp/screens/Tile.h" #include "displayapp/DisplayApp.h" #include "displayapp/screens/BatteryIcon.h" +#include "components/ble/BleController.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -26,46 +28,26 @@ Tile::Tile(uint8_t screenID, uint8_t numScreens, DisplayApp* app, Controllers::Settings& settingsController, - Pinetime::Controllers::Battery& batteryController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, std::array<Applications, 6>& applications) - : Screen(app), batteryController {batteryController}, dateTimeController {dateTimeController} { + : Screen(app), + dateTimeController {dateTimeController}, + pageIndicator(screenID, numScreens), + statusIcons(batteryController, bleController) { settingsController.SetAppMenu(screenID); + statusIcons.Create(); + lv_obj_align(statusIcons.GetObject(), lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -8, 0); + // Time label_time = lv_label_create(lv_scr_act(), nullptr); lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER); lv_obj_align(label_time, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); - // Battery - batteryIcon.Create(lv_scr_act()); - lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, -8, 0); - - if (numScreens > 1) { - pageIndicatorBasePoints[0].x = LV_HOR_RES - 1; - pageIndicatorBasePoints[0].y = 0; - pageIndicatorBasePoints[1].x = LV_HOR_RES - 1; - pageIndicatorBasePoints[1].y = LV_VER_RES; - - pageIndicatorBase = lv_line_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_line_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_color(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); - lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2); - - const uint16_t indicatorSize = LV_VER_RES / numScreens; - const uint16_t indicatorPos = indicatorSize * screenID; - - pageIndicatorPoints[0].x = LV_HOR_RES - 1; - pageIndicatorPoints[0].y = indicatorPos; - pageIndicatorPoints[1].x = LV_HOR_RES - 1; - pageIndicatorPoints[1].y = indicatorPos + indicatorSize; - - pageIndicator = lv_line_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_line_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xb0, 0xb0, 0xb0)); - lv_line_set_points(pageIndicator, pageIndicatorPoints, 2); - } + pageIndicator.Create(); uint8_t btIndex = 0; for (uint8_t i = 0; i < 6; i++) { @@ -90,7 +72,7 @@ Tile::Tile(uint8_t screenID, lv_obj_set_style_local_bg_opa(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, LV_OPA_50); lv_obj_set_style_local_bg_color(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, LV_COLOR_AQUA); lv_obj_set_style_local_bg_opa(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DISABLED, LV_OPA_50); - lv_obj_set_style_local_bg_color(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DISABLED, lv_color_hex(0x111111)); + lv_obj_set_style_local_bg_color(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DISABLED, Colors::bgDark); lv_obj_set_style_local_pad_all(btnm1, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 0); lv_obj_set_style_local_pad_inner(btnm1, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 10); @@ -116,7 +98,7 @@ Tile::~Tile() { void Tile::UpdateScreen() { lv_label_set_text(label_time, dateTimeController.FormattedTime().c_str()); - batteryIcon.SetBatteryPercentage(batteryController.PercentRemaining()); + statusIcons.Update(); } void Tile::OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId) { diff --git a/src/displayapp/screens/Tile.h b/src/displayapp/screens/Tile.h index 48747144..d8a68128 100644 --- a/src/displayapp/screens/Tile.h +++ b/src/displayapp/screens/Tile.h @@ -7,9 +7,9 @@ #include "displayapp/Apps.h" #include "components/datetime/DateTimeController.h" #include "components/settings/Settings.h" -#include "components/datetime/DateTimeController.h" #include "components/battery/BatteryController.h" -#include <displayapp/screens/BatteryIcon.h> +#include "displayapp/widgets/PageIndicator.h" +#include "displayapp/widgets/StatusIcons.h" namespace Pinetime { namespace Applications { @@ -25,7 +25,8 @@ namespace Pinetime { uint8_t numScreens, DisplayApp* app, Controllers::Settings& settingsController, - Pinetime::Controllers::Battery& batteryController, + Controllers::Battery& batteryController, + Controllers::Ble& bleController, Controllers::DateTime& dateTimeController, std::array<Applications, 6>& applications); @@ -35,19 +36,15 @@ namespace Pinetime { void OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId); private: - Pinetime::Controllers::Battery& batteryController; Controllers::DateTime& dateTimeController; lv_task_t* taskUpdate; lv_obj_t* label_time; - lv_point_t pageIndicatorBasePoints[2]; - lv_point_t pageIndicatorPoints[2]; - lv_obj_t* pageIndicatorBase; - lv_obj_t* pageIndicator; lv_obj_t* btnm1; - BatteryIcon batteryIcon; + Widgets::PageIndicator pageIndicator; + Widgets::StatusIcons statusIcons; const char* btnmMap[8]; Pinetime::Applications::Apps apps[6]; diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index a1df662a..136d6b52 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -1,13 +1,20 @@ #include "displayapp/screens/Timer.h" #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" #include <lvgl/lvgl.h> using namespace Pinetime::Applications::Screens; static void btnEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast<Timer*>(obj->user_data); - screen->OnButtonEvent(obj, event); + if (event == LV_EVENT_PRESSED) { + screen->ButtonPressed(); + } else if (event == LV_EVENT_RELEASED || event == LV_EVENT_PRESS_LOST) { + screen->MaskReset(); + } else if (event == LV_EVENT_SHORT_CLICKED) { + screen->ToggleRunning(); + } } Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : Screen(app), timerController {timerController} { @@ -23,14 +30,37 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController) : S lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); lv_obj_align(secondCounter.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); + highlightObjectMask = lv_objmask_create(lv_scr_act(), nullptr); + lv_obj_set_size(highlightObjectMask, 240, 50); + lv_obj_align(highlightObjectMask, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + lv_draw_mask_line_param_t tmpMaskLine; + + lv_draw_mask_line_points_init(&tmpMaskLine, 0, 0, 0, 240, LV_DRAW_MASK_LINE_SIDE_LEFT); + highlightMask = lv_objmask_add_mask(highlightObjectMask, &tmpMaskLine); + + lv_obj_t* btnHighlight = lv_obj_create(highlightObjectMask, nullptr); + lv_obj_set_style_local_radius(btnHighlight, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_style_local_bg_color(btnHighlight, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + lv_obj_set_size(btnHighlight, LV_HOR_RES, 50); + lv_obj_align(btnHighlight, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + btnObjectMask = lv_objmask_create(lv_scr_act(), nullptr); + lv_obj_set_size(btnObjectMask, 240, 50); + lv_obj_align(btnObjectMask, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + lv_draw_mask_line_points_init(&tmpMaskLine, 0, 0, 0, 240, LV_DRAW_MASK_LINE_SIDE_RIGHT); + btnMask = lv_objmask_add_mask(btnObjectMask, &tmpMaskLine); + + btnPlayPause = lv_btn_create(btnObjectMask, nullptr); btnPlayPause->user_data = this; lv_obj_set_style_local_radius(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x38, 0x38, 0x38)); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_event_cb(btnPlayPause, btnEventHandler); lv_obj_set_size(btnPlayPause, LV_HOR_RES, 50); - lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); - txtPlayPause = lv_label_create(btnPlayPause, nullptr); + + txtPlayPause = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(txtPlayPause, btnPlayPause, LV_ALIGN_CENTER, 0, 0); if (timerController.IsRunning()) { SetTimerRunning(); @@ -46,11 +76,46 @@ Timer::~Timer() { lv_obj_clean(lv_scr_act()); } +void Timer::ButtonPressed() { + pressTime = xTaskGetTickCount(); + buttonPressing = true; +} + +void Timer::MaskReset() { + buttonPressing = false; + // A click event is processed before a release event, + // so the release event would override the "Pause" text without this check + if (!timerController.IsRunning()) { + lv_label_set_text_static(txtPlayPause, "Start"); + } + maskPosition = 0; + UpdateMask(); +} + +void Timer::UpdateMask() { + lv_draw_mask_line_param_t maskLine; + + lv_draw_mask_line_points_init(&maskLine, maskPosition, 0, maskPosition, 240, LV_DRAW_MASK_LINE_SIDE_LEFT); + lv_objmask_update_mask(highlightObjectMask, highlightMask, &maskLine); + + lv_draw_mask_line_points_init(&maskLine, maskPosition, 0, maskPosition, 240, LV_DRAW_MASK_LINE_SIDE_RIGHT); + lv_objmask_update_mask(btnObjectMask, btnMask, &maskLine); +} + void Timer::Refresh() { if (timerController.IsRunning()) { uint32_t seconds = timerController.GetTimeRemaining() / 1000; minuteCounter.SetValue(seconds / 60); secondCounter.SetValue(seconds % 60); + } else if (buttonPressing && xTaskGetTickCount() > pressTime + pdMS_TO_TICKS(150)) { + lv_label_set_text_static(txtPlayPause, "Reset"); + maskPosition += 15; + if (maskPosition > 240) { + MaskReset(); + Reset(); + } else { + UpdateMask(); + } } } @@ -66,25 +131,21 @@ void Timer::SetTimerStopped() { lv_label_set_text_static(txtPlayPause, "Start"); } -void Timer::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { - if (event == LV_EVENT_CLICKED) { - if (obj == btnPlayPause) { - if (timerController.IsRunning()) { - uint32_t seconds = timerController.GetTimeRemaining() / 1000; - minuteCounter.SetValue(seconds / 60); - secondCounter.SetValue(seconds % 60); - timerController.StopTimer(); - SetTimerStopped(); - } else if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { - timerController.StartTimer((secondCounter.GetValue() + minuteCounter.GetValue() * 60) * 1000); - Refresh(); - SetTimerRunning(); - } - } +void Timer::ToggleRunning() { + if (timerController.IsRunning()) { + uint32_t seconds = timerController.GetTimeRemaining() / 1000; + minuteCounter.SetValue(seconds / 60); + secondCounter.SetValue(seconds % 60); + timerController.StopTimer(); + SetTimerStopped(); + } else if (secondCounter.GetValue() + minuteCounter.GetValue() > 0) { + timerController.StartTimer((secondCounter.GetValue() + minuteCounter.GetValue() * 60) * 1000); + Refresh(); + SetTimerRunning(); } } -void Timer::SetDone() { +void Timer::Reset() { minuteCounter.SetValue(0); secondCounter.SetValue(0); SetTimerStopped(); diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index 2797a4fa..a6b60a17 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -5,29 +5,42 @@ #include "systemtask/SystemTask.h" #include "displayapp/LittleVgl.h" #include "displayapp/widgets/Counter.h" +#include <lvgl/lvgl.h> #include "components/timer/TimerController.h" namespace Pinetime::Applications::Screens { class Timer : public Screen { public: - enum class Modes { Normal, Done }; - Timer(DisplayApp* app, Controllers::TimerController& timerController); ~Timer() override; void Refresh() override; - void SetDone(); - void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + void Reset(); + void ToggleRunning(); + void ButtonPressed(); + void MaskReset(); private: void SetTimerRunning(); void SetTimerStopped(); + void UpdateMask(); Controllers::TimerController& timerController; + lv_obj_t* msecTime; lv_obj_t* btnPlayPause; lv_obj_t* txtPlayPause; + + lv_obj_t* btnObjectMask; + lv_obj_t* highlightObjectMask; + lv_objmask_mask_t* btnMask; + lv_objmask_mask_t* highlightMask; + lv_task_t* taskRefresh; - Widgets::Counter minuteCounter = Widgets::Counter(0, 59); - Widgets::Counter secondCounter = Widgets::Counter(0, 59); + Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + Widgets::Counter secondCounter = Widgets::Counter(0, 59, jetbrains_mono_76); + + bool buttonPressing = false; + int maskPosition = 0; + TickType_t pressTime; }; } diff --git a/src/displayapp/screens/Twos.cpp b/src/displayapp/screens/Twos.cpp index 7e465fcd..5d1f4980 100644 --- a/src/displayapp/screens/Twos.cpp +++ b/src/displayapp/screens/Twos.cpp @@ -1,10 +1,7 @@ #include "displayapp/screens/Twos.h" -#include <array> #include <cstdio> #include <cstdlib> #include <lvgl/lvgl.h> -#include <utility> -#include <vector> using namespace Pinetime::Applications::Screens; @@ -21,33 +18,33 @@ Twos::Twos(Pinetime::Applications::DisplayApp* app) : Screen(app) { lv_style_set_border_width(&style_cell1, LV_STATE_DEFAULT, 3); lv_style_set_bg_opa(&style_cell1, LV_STATE_DEFAULT, LV_OPA_COVER); lv_style_set_bg_color(&style_cell1, LV_STATE_DEFAULT, lv_color_hex(0xcdc0b4)); - lv_style_set_pad_top(&style_cell1, LV_STATE_DEFAULT, 25); + lv_style_set_pad_top(&style_cell1, LV_STATE_DEFAULT, 29); lv_style_set_text_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_style_set_border_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); lv_style_set_border_width(&style_cell2, LV_STATE_DEFAULT, 3); lv_style_set_bg_opa(&style_cell2, LV_STATE_DEFAULT, LV_OPA_COVER); lv_style_set_bg_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xefdfc6)); - lv_style_set_pad_top(&style_cell2, LV_STATE_DEFAULT, 25); + lv_style_set_pad_top(&style_cell2, LV_STATE_DEFAULT, 29); lv_style_set_text_color(&style_cell2, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_style_set_border_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); lv_style_set_border_width(&style_cell3, LV_STATE_DEFAULT, 3); lv_style_set_bg_opa(&style_cell3, LV_STATE_DEFAULT, LV_OPA_COVER); lv_style_set_bg_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xef9263)); - lv_style_set_pad_top(&style_cell3, LV_STATE_DEFAULT, 25); + lv_style_set_pad_top(&style_cell3, LV_STATE_DEFAULT, 29); lv_style_set_border_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); lv_style_set_border_width(&style_cell4, LV_STATE_DEFAULT, 3); lv_style_set_bg_opa(&style_cell4, LV_STATE_DEFAULT, LV_OPA_COVER); lv_style_set_bg_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xf76142)); - lv_style_set_pad_top(&style_cell4, LV_STATE_DEFAULT, 25); + lv_style_set_pad_top(&style_cell4, LV_STATE_DEFAULT, 29); lv_style_set_border_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0xbbada0)); lv_style_set_border_width(&style_cell5, LV_STATE_DEFAULT, 3); lv_style_set_bg_opa(&style_cell5, LV_STATE_DEFAULT, LV_OPA_COVER); lv_style_set_bg_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0x007dc5)); - lv_style_set_pad_top(&style_cell5, LV_STATE_DEFAULT, 25); + lv_style_set_pad_top(&style_cell5, LV_STATE_DEFAULT, 29); // format grid display @@ -57,24 +54,22 @@ Twos::Twos(Pinetime::Applications::DisplayApp* app) : Screen(app) { lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL3, &style_cell3); lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL4, &style_cell4); lv_obj_add_style(gridDisplay, LV_TABLE_PART_CELL4 + 1, &style_cell5); - lv_table_set_col_cnt(gridDisplay, 4); - lv_table_set_row_cnt(gridDisplay, 4); - lv_table_set_col_width(gridDisplay, 0, LV_HOR_RES / 4); - lv_table_set_col_width(gridDisplay, 1, LV_HOR_RES / 4); - lv_table_set_col_width(gridDisplay, 2, LV_HOR_RES / 4); - lv_table_set_col_width(gridDisplay, 3, LV_HOR_RES / 4); - lv_obj_align(gridDisplay, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - - lv_obj_clean_style_list(gridDisplay, LV_TABLE_PART_BG); - - // initialize grid - for (int row = 0; row < 4; row++) { - for (int col = 0; col < 4; col++) { + lv_table_set_col_cnt(gridDisplay, nCols); + lv_table_set_row_cnt(gridDisplay, nRows); + for (int col = 0; col < nCols; col++) { + static constexpr int colWidth = LV_HOR_RES_MAX / nCols; + lv_table_set_col_width(gridDisplay, col, colWidth); + for (int row = 0; row < nRows; row++) { grid[row][col].value = 0; lv_table_set_cell_type(gridDisplay, row, col, 1); lv_table_set_cell_align(gridDisplay, row, col, LV_LABEL_ALIGN_CENTER); } } + // Move one pixel down to remove a gap + lv_obj_align(gridDisplay, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 1); + + lv_obj_clean_style_list(gridDisplay, LV_TABLE_PART_BG); + placeNewTile(); placeNewTile(); @@ -82,7 +77,7 @@ Twos::Twos(Pinetime::Applications::DisplayApp* app) : Screen(app) { scoreText = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_width(scoreText, LV_HOR_RES); lv_label_set_align(scoreText, LV_ALIGN_IN_LEFT_MID); - lv_obj_align(scoreText, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 10); + lv_obj_align(scoreText, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); lv_label_set_recolor(scoreText, true); lv_label_set_text_fmt(scoreText, "Score #FFFF00 %i#", score); } @@ -97,39 +92,38 @@ Twos::~Twos() { } bool Twos::placeNewTile() { - std::vector<std::pair<int, int>> availableCells; - for (int row = 0; row < 4; row++) { - for (int col = 0; col < 4; col++) { - if (!grid[row][col].value) { - availableCells.push_back(std::make_pair(row, col)); - } + unsigned int emptyCells[nCells]; + unsigned int nEmpty = 0; + for (unsigned int i = 0; i < nCells; i++) { + const unsigned int row = i / nCols; + const unsigned int col = i % nCols; + if (grid[row][col].value == 0) { + emptyCells[nEmpty] = i; + nEmpty++; } } - if (availableCells.size() == 0) { + if (nEmpty == 0) { return false; // game lost } - auto it = availableCells.cbegin(); - int random = rand() % availableCells.size(); - std::advance(it, random); - std::pair<int, int> newCell = *it; + int random = rand() % nEmpty; - if ((rand() % 100) < 90) - grid[newCell.first][newCell.second].value = 2; - else - grid[newCell.first][newCell.second].value = 4; - updateGridDisplay(grid); + if ((rand() % 100) < 90) { + grid[emptyCells[random] / nCols][emptyCells[random] % nCols].value = 2; + } else { + grid[emptyCells[random] / nCols][emptyCells[random] % nCols].value = 4; + } + updateGridDisplay(); return true; } -bool Twos::tryMerge(TwosTile grid[][4], int& newRow, int& newCol, int oldRow, int oldCol) { +bool Twos::tryMerge(int newRow, int newCol, int oldRow, int oldCol) { if (grid[newRow][newCol].value == grid[oldRow][oldCol].value) { if ((newCol != oldCol) || (newRow != oldRow)) { if (!grid[newRow][newCol].merged) { - unsigned int newVal = grid[oldRow][oldCol].value *= 2; - grid[newRow][newCol].value = newVal; - score += newVal; + grid[newRow][newCol].value *= 2; + score += grid[newRow][newCol].value; lv_label_set_text_fmt(scoreText, "Score #FFFF00 %i#", score); grid[oldRow][oldCol].value = 0; grid[newRow][newCol].merged = true; @@ -140,7 +134,7 @@ bool Twos::tryMerge(TwosTile grid[][4], int& newRow, int& newCol, int oldRow, in return false; } -bool Twos::tryMove(TwosTile grid[][4], int newRow, int newCol, int oldRow, int oldCol) { +bool Twos::tryMove(int newRow, int newCol, int oldRow, int oldCol) { if (((newCol >= 0) && (newCol != oldCol)) || ((newRow >= 0) && (newRow != oldRow))) { grid[newRow][newCol].value = grid[oldRow][oldCol].value; grid[oldRow][oldCol].value = 0; @@ -151,28 +145,30 @@ bool Twos::tryMove(TwosTile grid[][4], int newRow, int newCol, int oldRow, int o bool Twos::OnTouchEvent(Pinetime::Applications::TouchEvents event) { bool validMove = false; - for (int row = 0; row < 4; row++) { - for (int col = 0; col < 4; col++) { - grid[row][col].merged = false; // reinitialize merge state - } + for (unsigned int i = 0; i < nCells; i++) { + const unsigned int row = i / nCols; + const unsigned int col = i % nCols; + grid[row][col].merged = false; // reinitialize merge state } switch (event) { case TouchEvents::SwipeLeft: - for (int col = 1; col < 4; col++) { // ignore tiles already on far left - for (int row = 0; row < 4; row++) { - if (grid[row][col].value) { + for (int col = 1; col < nCols; col++) { // ignore tiles already on far left + for (int row = 0; row < nRows; row++) { + if (grid[row][col].value > 0) { int newCol = -1; for (int potentialNewCol = col - 1; potentialNewCol >= 0; potentialNewCol--) { - if (!grid[row][potentialNewCol].value) { + if (grid[row][potentialNewCol].value == 0) { newCol = potentialNewCol; } else { // blocked by another tile - if (tryMerge(grid, row, potentialNewCol, row, col)) + if (tryMerge(row, potentialNewCol, row, col)) { validMove = true; + } break; } } - if (tryMove(grid, row, newCol, row, col)) + if (tryMove(row, newCol, row, col)) { validMove = true; + } } } } @@ -181,21 +177,23 @@ bool Twos::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } return true; case TouchEvents::SwipeRight: - for (int col = 2; col >= 0; col--) { // ignore tiles already on far right - for (int row = 0; row < 4; row++) { - if (grid[row][col].value) { + for (int col = nCols - 2; col >= 0; col--) { // ignore tiles already on far right + for (int row = 0; row < nRows; row++) { + if (grid[row][col].value > 0) { int newCol = -1; - for (int potentialNewCol = col + 1; potentialNewCol < 4; potentialNewCol++) { - if (!grid[row][potentialNewCol].value) { + for (int potentialNewCol = col + 1; potentialNewCol < nCols; potentialNewCol++) { + if (grid[row][potentialNewCol].value == 0) { newCol = potentialNewCol; } else { // blocked by another tile - if (tryMerge(grid, row, potentialNewCol, row, col)) + if (tryMerge(row, potentialNewCol, row, col)) { validMove = true; + } break; } } - if (tryMove(grid, row, newCol, row, col)) + if (tryMove(row, newCol, row, col)) { validMove = true; + } } } } @@ -204,21 +202,23 @@ bool Twos::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } return true; case TouchEvents::SwipeUp: - for (int row = 1; row < 4; row++) { // ignore tiles already on top - for (int col = 0; col < 4; col++) { - if (grid[row][col].value) { + for (int row = 1; row < nRows; row++) { // ignore tiles already on top + for (int col = 0; col < nCols; col++) { + if (grid[row][col].value > 0) { int newRow = -1; for (int potentialNewRow = row - 1; potentialNewRow >= 0; potentialNewRow--) { - if (!grid[potentialNewRow][col].value) { + if (grid[potentialNewRow][col].value == 0) { newRow = potentialNewRow; } else { // blocked by another tile - if (tryMerge(grid, potentialNewRow, col, row, col)) + if (tryMerge(potentialNewRow, col, row, col)) { validMove = true; + } break; } } - if (tryMove(grid, newRow, col, row, col)) + if (tryMove(newRow, col, row, col)) { validMove = true; + } } } } @@ -227,21 +227,23 @@ bool Twos::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } return true; case TouchEvents::SwipeDown: - for (int row = 2; row >= 0; row--) { // ignore tiles already on bottom - for (int col = 0; col < 4; col++) { - if (grid[row][col].value) { + for (int row = nRows - 2; row >= 0; row--) { // ignore tiles already on bottom + for (int col = 0; col < nCols; col++) { + if (grid[row][col].value > 0) { int newRow = -1; - for (int potentialNewRow = row + 1; potentialNewRow < 4; potentialNewRow++) { - if (!grid[potentialNewRow][col].value) { + for (int potentialNewRow = row + 1; potentialNewRow < nRows; potentialNewRow++) { + if (grid[potentialNewRow][col].value == 0) { newRow = potentialNewRow; } else { // blocked by another tile - if (tryMerge(grid, potentialNewRow, col, row, col)) + if (tryMerge(potentialNewRow, col, row, col)) { validMove = true; + } break; } } - if (tryMove(grid, newRow, col, row, col)) + if (tryMove(newRow, col, row, col)) { validMove = true; + } } } } @@ -255,36 +257,36 @@ bool Twos::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return false; } -void Twos::updateGridDisplay(TwosTile grid[][4]) { - for (int row = 0; row < 4; row++) { - for (int col = 0; col < 4; col++) { - if (grid[row][col].value) { - char buffer[7]; - sprintf(buffer, "%d", grid[row][col].value); - lv_table_set_cell_value(gridDisplay, row, col, buffer); - } else { - lv_table_set_cell_value(gridDisplay, row, col, ""); - } - switch (grid[row][col].value) { - case 0: - lv_table_set_cell_type(gridDisplay, row, col, 1); - break; - case 2: - case 4: - lv_table_set_cell_type(gridDisplay, row, col, 2); - break; - case 8: - case 16: - lv_table_set_cell_type(gridDisplay, row, col, 3); - break; - case 32: - case 64: - lv_table_set_cell_type(gridDisplay, row, col, 4); - break; - default: - lv_table_set_cell_type(gridDisplay, row, col, 5); - break; - } +void Twos::updateGridDisplay() { + for (unsigned int i = 0; i < nCells; i++) { + const unsigned int row = i / nCols; + const unsigned int col = i % nCols; + if (grid[row][col].value > 0) { + char buffer[7]; + sprintf(buffer, "%d", grid[row][col].value); + lv_table_set_cell_value(gridDisplay, row, col, buffer); + } else { + lv_table_set_cell_value(gridDisplay, row, col, ""); + } + switch (grid[row][col].value) { + case 0: + lv_table_set_cell_type(gridDisplay, row, col, 1); + break; + case 2: + case 4: + lv_table_set_cell_type(gridDisplay, row, col, 2); + break; + case 8: + case 16: + lv_table_set_cell_type(gridDisplay, row, col, 3); + break; + case 32: + case 64: + lv_table_set_cell_type(gridDisplay, row, col, 4); + break; + default: + lv_table_set_cell_type(gridDisplay, row, col, 5); + break; } } } diff --git a/src/displayapp/screens/Twos.h b/src/displayapp/screens/Twos.h index 5a0c4350..4a6ada0b 100644 --- a/src/displayapp/screens/Twos.h +++ b/src/displayapp/screens/Twos.h @@ -26,11 +26,14 @@ namespace Pinetime { lv_obj_t* scoreText; lv_obj_t* gridDisplay; - TwosTile grid[4][4]; + static constexpr int nCols = 4; + static constexpr int nRows = 4; + static constexpr int nCells = nCols * nRows; + TwosTile grid[nRows][nCols]; unsigned int score = 0; - void updateGridDisplay(TwosTile grid[][4]); - bool tryMerge(TwosTile grid[][4], int& newRow, int& newCol, int oldRow, int oldCol); - bool tryMove(TwosTile grid[][4], int newRow, int newCol, int oldRow, int oldCol); + void updateGridDisplay(); + bool tryMerge(int newRow, int newCol, int oldRow, int oldCol); + bool tryMove(int newRow, int newCol, int oldRow, int oldCol); bool placeNewTile(); }; } diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 251a560f..5ebb3304 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -6,6 +6,7 @@ #include "displayapp/screens/Symbols.h" #include "displayapp/screens/NotificationIcon.h" #include "components/settings/Settings.h" +#include "displayapp/InfiniTimeTheme.h" LV_IMG_DECLARE(bg_clock); @@ -73,14 +74,14 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app, lv_obj_align(plugIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); notificationIcon = lv_label_create(lv_scr_act(), NULL); - lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME); lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); // Date - Day / Week day label_date_day = lv_label_create(lv_scr_act(), NULL); - lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0xff, 0xb0, 0x0)); + lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); lv_label_set_align(label_date_day, LV_LABEL_ALIGN_CENTER); lv_obj_align(label_date_day, NULL, LV_ALIGN_CENTER, 50, 0); diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index d10f8532..705272f7 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -3,8 +3,6 @@ #include <date/date.h> #include <lvgl/lvgl.h> #include <cstdio> -#include "displayapp/screens/BatteryIcon.h" -#include "displayapp/screens/BleIcon.h" #include "displayapp/screens/NotificationIcon.h" #include "displayapp/screens/Symbols.h" #include "components/battery/BatteryController.h" @@ -13,6 +11,7 @@ #include "components/heartrate/HeartRateController.h" #include "components/motion/MotionController.h" #include "components/settings/Settings.h" + using namespace Pinetime::Applications::Screens; WatchFaceDigital::WatchFaceDigital(DisplayApp* app, @@ -26,28 +25,16 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, : Screen(app), currentDateTime {{}}, dateTimeController {dateTimeController}, - batteryController {batteryController}, - bleController {bleController}, notificatioManager {notificatioManager}, settingsController {settingsController}, heartRateController {heartRateController}, - motionController {motionController} { - - batteryIcon.Create(lv_scr_act()); - lv_obj_align(batteryIcon.GetObject(), lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); + motionController {motionController}, + statusIcons(batteryController, bleController) { - batteryPlug = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000)); - lv_label_set_text_static(batteryPlug, Symbols::plug); - lv_obj_align(batteryPlug, batteryIcon.GetObject(), LV_ALIGN_OUT_LEFT_MID, -5, 0); - - bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082FC)); - lv_label_set_text_static(bleIcon, Symbols::bluetooth); - lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); + statusIcons.Create(); notificationIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME); lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); @@ -94,24 +81,7 @@ WatchFaceDigital::~WatchFaceDigital() { } void WatchFaceDigital::Refresh() { - powerPresent = batteryController.IsPowerPresent(); - if (powerPresent.IsUpdated()) { - lv_label_set_text_static(batteryPlug, BatteryIcon::GetPlugIcon(powerPresent.Get())); - } - - batteryPercentRemaining = batteryController.PercentRemaining(); - if (batteryPercentRemaining.IsUpdated()) { - auto batteryPercent = batteryPercentRemaining.Get(); - batteryIcon.SetBatteryPercentage(batteryPercent); - } - - bleState = bleController.IsConnected(); - bleRadioEnabled = bleController.IsRadioEnabled(); - if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { - lv_label_set_text_static(bleIcon, BleIcon::GetIcon(bleState.Get())); - } - lv_obj_realign(batteryPlug); - lv_obj_realign(bleIcon); + statusIcons.Update(); notificationState = notificatioManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index bd27806f..49935792 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -1,6 +1,5 @@ #pragma once -#include <displayapp/screens/BatteryIcon.h> #include <lvgl/src/lv_core/lv_obj.h> #include <chrono> #include <cstdint> @@ -8,6 +7,7 @@ #include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" #include "components/ble/BleController.h" +#include "displayapp/widgets/StatusIcons.h" namespace Pinetime { namespace Controllers { @@ -59,25 +59,20 @@ namespace Pinetime { lv_obj_t* label_time; lv_obj_t* label_time_ampm; lv_obj_t* label_date; - lv_obj_t* bleIcon; - lv_obj_t* batteryPlug; lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatValue; lv_obj_t* stepIcon; lv_obj_t* stepValue; lv_obj_t* notificationIcon; - BatteryIcon batteryIcon; - Controllers::DateTime& dateTimeController; - Controllers::Battery& batteryController; - Controllers::Ble& bleController; Controllers::NotificationManager& notificatioManager; Controllers::Settings& settingsController; Controllers::HeartRateController& heartRateController; Controllers::MotionController& motionController; lv_task_t* taskRefresh; + Widgets::StatusIcons statusIcons; }; } } diff --git a/src/displayapp/screens/WatchFacePineTimeStyle.cpp b/src/displayapp/screens/WatchFacePineTimeStyle.cpp index dad2f4c7..ed09f5dd 100644 --- a/src/displayapp/screens/WatchFacePineTimeStyle.cpp +++ b/src/displayapp/screens/WatchFacePineTimeStyle.cpp @@ -42,13 +42,6 @@ namespace { auto* screen = static_cast<WatchFacePineTimeStyle*>(obj->user_data); screen->UpdateSelected(obj, event); } - - bool IsBleIconVisible(bool isRadioEnabled, bool isConnected) { - if (!isRadioEnabled) { - return true; - } - return isConnected; - } } WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, @@ -111,11 +104,11 @@ WatchFacePineTimeStyle::WatchFacePineTimeStyle(DisplayApp* app, lv_obj_align(plugIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2); bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_label_set_text_static(bleIcon, ""); notificationIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_label_set_text_static(notificationIcon, ""); // Calendar icon diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index c899648c..f5490b44 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -149,7 +149,7 @@ void WatchFaceTerminal::Refresh() { } if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { - lv_label_set_text_fmt(label_date, "[DATE]#007fff %04d.%02d.%02d#", short(year), char(month), char(day)); + lv_label_set_text_fmt(label_date, "[DATE]#007fff %04d-%02d-%02d#", short(year), char(month), char(day)); currentYear = year; currentMonth = month; diff --git a/src/displayapp/screens/settings/QuickSettings.cpp b/src/displayapp/screens/settings/QuickSettings.cpp index 708d5109..b76affc9 100644 --- a/src/displayapp/screens/settings/QuickSettings.cpp +++ b/src/displayapp/screens/settings/QuickSettings.cpp @@ -2,19 +2,29 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" #include "displayapp/screens/BatteryIcon.h" +#include "components/ble/BleController.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; namespace { void ButtonEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast<QuickSettings*>(obj->user_data); - screen->OnButtonEvent(obj, event); + if (event == LV_EVENT_CLICKED) { + screen->OnButtonEvent(obj); + } } void lv_update_task(struct _lv_task_t* task) { auto* user_data = static_cast<QuickSettings*>(task->user_data); user_data->UpdateScreen(); } + + enum class ButtonState : lv_state_t { + NotificationsOn = LV_STATE_CHECKED, + NotificationsOff = LV_STATE_DEFAULT, + Sleep = 0x40, + }; } QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, @@ -22,13 +32,16 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, Controllers::DateTime& dateTimeController, Controllers::BrightnessController& brightness, Controllers::MotorController& motorController, - Pinetime::Controllers::Settings& settingsController) + Pinetime::Controllers::Settings& settingsController, + Controllers::Ble& bleController) : Screen(app), - batteryController {batteryController}, dateTimeController {dateTimeController}, brightness {brightness}, motorController {motorController}, - settingsController {settingsController} { + settingsController {settingsController}, + statusIcons(batteryController, bleController) { + + statusIcons.Create(); // This is the distance (padding) between all objects on this screen. static constexpr uint8_t innerDistance = 10; @@ -38,9 +51,6 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); - batteryIcon.Create(lv_scr_act()); - lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - static constexpr uint8_t barHeight = 20 + innerDistance; static constexpr uint8_t buttonHeight = (LV_VER_RES_MAX - barHeight - innerDistance) / 2; static constexpr uint8_t buttonWidth = (LV_HOR_RES_MAX - innerDistance) / 2; // wide buttons @@ -49,7 +59,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, lv_style_init(&btn_style); lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, buttonHeight / 4); - lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x38, 0x38, 0x38)); + lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, Colors::bgAlt); btn1 = lv_btn_create(lv_scr_act(), nullptr); btn1->user_data = this; @@ -72,25 +82,29 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app, lv_obj_t* lbl_btn; lbl_btn = lv_label_create(btn2, nullptr); lv_obj_set_style_local_text_font(lbl_btn, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); - lv_label_set_text_static(lbl_btn, Symbols::highlight); + lv_label_set_text_static(lbl_btn, Symbols::flashlight); btn3 = lv_btn_create(lv_scr_act(), nullptr); btn3->user_data = this; lv_obj_set_event_cb(btn3, ButtonEventHandler); - lv_btn_set_checkable(btn3, true); lv_obj_add_style(btn3, LV_BTN_PART_MAIN, &btn_style); - lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, static_cast<lv_state_t>(ButtonState::NotificationsOff), LV_COLOR_RED); + static constexpr lv_color_t violet = LV_COLOR_MAKE(0x60, 0x00, 0xff); + lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, static_cast<lv_state_t>(ButtonState::Sleep), violet); lv_obj_set_size(btn3, buttonWidth, buttonHeight); lv_obj_align(btn3, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, buttonXOffset, 0); btn3_lvl = lv_label_create(btn3, nullptr); lv_obj_set_style_local_text_font(btn3_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); - if (settingsController.GetNotificationStatus() == Controllers::Settings::Notification::ON) { - lv_obj_add_state(btn3, LV_STATE_CHECKED); + if (settingsController.GetNotificationStatus() == Controllers::Settings::Notification::On) { lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn); - } else { + lv_obj_set_state(btn3, static_cast<lv_state_t>(ButtonState::NotificationsOn)); + } else if (settingsController.GetNotificationStatus() == Controllers::Settings::Notification::Off) { lv_label_set_text_static(btn3_lvl, Symbols::notificationsOff); + } else { + lv_label_set_text_static(btn3_lvl, Symbols::sleep); + lv_obj_set_state(btn3, static_cast<lv_state_t>(ButtonState::Sleep)); } btn4 = lv_btn_create(lv_scr_act(), nullptr); @@ -118,34 +132,36 @@ QuickSettings::~QuickSettings() { void QuickSettings::UpdateScreen() { lv_label_set_text(label_time, dateTimeController.FormattedTime().c_str()); - batteryIcon.SetBatteryPercentage(batteryController.PercentRemaining()); + statusIcons.Update(); } -void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) { - if (object == btn2 && event == LV_EVENT_CLICKED) { - - running = false; +void QuickSettings::OnButtonEvent(lv_obj_t* object) { + if (object == btn2) { app->StartApp(Apps::FlashLight, DisplayApp::FullRefreshDirections::Up); - - } else if (object == btn1 && event == LV_EVENT_CLICKED) { + } else if (object == btn1) { brightness.Step(); lv_label_set_text_static(btn1_lvl, brightness.GetIcon()); settingsController.SetBrightness(brightness.Level()); - } else if (object == btn3 && event == LV_EVENT_VALUE_CHANGED) { + } else if (object == btn3) { - if (lv_obj_get_state(btn3, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) { - settingsController.SetNotificationStatus(Controllers::Settings::Notification::ON); - motorController.RunForDuration(35); - lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn); - } else { - settingsController.SetNotificationStatus(Controllers::Settings::Notification::OFF); + if (settingsController.GetNotificationStatus() == Controllers::Settings::Notification::On) { + settingsController.SetNotificationStatus(Controllers::Settings::Notification::Off); lv_label_set_text_static(btn3_lvl, Symbols::notificationsOff); + lv_obj_set_state(btn3, static_cast<lv_state_t>(ButtonState::NotificationsOff)); + } else if (settingsController.GetNotificationStatus() == Controllers::Settings::Notification::Off) { + settingsController.SetNotificationStatus(Controllers::Settings::Notification::Sleep); + lv_label_set_text_static(btn3_lvl, Symbols::sleep); + lv_obj_set_state(btn3, static_cast<lv_state_t>(ButtonState::Sleep)); + } else { + settingsController.SetNotificationStatus(Controllers::Settings::Notification::On); + lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn); + lv_obj_set_state(btn3, static_cast<lv_state_t>(ButtonState::NotificationsOn)); + motorController.RunForDuration(35); } - } else if (object == btn4 && event == LV_EVENT_CLICKED) { - running = false; + } else if (object == btn4) { settingsController.SetSettingsMenu(0); app->StartApp(Apps::Settings, DisplayApp::FullRefreshDirections::Up); } diff --git a/src/displayapp/screens/settings/QuickSettings.h b/src/displayapp/screens/settings/QuickSettings.h index 40a2a2ef..f555d034 100644 --- a/src/displayapp/screens/settings/QuickSettings.h +++ b/src/displayapp/screens/settings/QuickSettings.h @@ -8,7 +8,7 @@ #include "components/motor/MotorController.h" #include "components/settings/Settings.h" #include "components/battery/BatteryController.h" -#include <displayapp/screens/BatteryIcon.h> +#include "displayapp/widgets/StatusIcons.h" namespace Pinetime { @@ -22,16 +22,16 @@ namespace Pinetime { Controllers::DateTime& dateTimeController, Controllers::BrightnessController& brightness, Controllers::MotorController& motorController, - Pinetime::Controllers::Settings& settingsController); + Pinetime::Controllers::Settings& settingsController, + Controllers::Ble& bleController); ~QuickSettings() override; - void OnButtonEvent(lv_obj_t* object, lv_event_t event); + void OnButtonEvent(lv_obj_t* object); void UpdateScreen(); private: - Pinetime::Controllers::Battery& batteryController; Controllers::DateTime& dateTimeController; Controllers::BrightnessController& brightness; Controllers::MotorController& motorController; @@ -49,7 +49,7 @@ namespace Pinetime { lv_obj_t* btn3_lvl; lv_obj_t* btn4; - BatteryIcon batteryIcon; + Widgets::StatusIcons statusIcons; }; } } diff --git a/src/displayapp/screens/settings/SettingChimes.cpp b/src/displayapp/screens/settings/SettingChimes.cpp index d53d4da6..7f519f75 100644 --- a/src/displayapp/screens/settings/SettingChimes.cpp +++ b/src/displayapp/screens/settings/SettingChimes.cpp @@ -14,6 +14,8 @@ namespace { } } +constexpr std::array<SettingChimes::Option, 3> SettingChimes::options; + SettingChimes::SettingChimes(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { @@ -40,37 +42,16 @@ SettingChimes::SettingChimes(Pinetime::Applications::DisplayApp* app, Pinetime:: lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - optionsTotal = 0; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Off"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - SetRadioButtonStyle(cbOption[optionsTotal]); - if (settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::None) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Every hour"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - SetRadioButtonStyle(cbOption[optionsTotal]); - if (settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Every 30 mins"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - SetRadioButtonStyle(cbOption[optionsTotal]); - if (settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); + for (unsigned int i = 0; i < options.size(); i++) { + cbOption[i] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text(cbOption[i], options[i].name); + if (settingsController.GetChimeOption() == options[i].chimesOption) { + lv_checkbox_set_checked(cbOption[i], true); + } + cbOption[i]->user_data = this; + lv_obj_set_event_cb(cbOption[i], event_handler); + SetRadioButtonStyle(cbOption[i]); } - - optionsTotal++; } SettingChimes::~SettingChimes() { @@ -80,18 +61,10 @@ SettingChimes::~SettingChimes() { void SettingChimes::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_VALUE_CHANGED) { - for (uint8_t i = 0; i < optionsTotal; i++) { + for (uint8_t i = 0; i < options.size(); i++) { if (object == cbOption[i]) { lv_checkbox_set_checked(cbOption[i], true); - if (i == 0) { - settingsController.SetChimeOption(Controllers::Settings::ChimesOption::None); - } - if (i == 1) { - settingsController.SetChimeOption(Controllers::Settings::ChimesOption::Hours); - } - if (i == 2) { - settingsController.SetChimeOption(Controllers::Settings::ChimesOption::HalfHours); - } + settingsController.SetChimeOption(options[i].chimesOption); } else { lv_checkbox_set_checked(cbOption[i], false); } diff --git a/src/displayapp/screens/settings/SettingChimes.h b/src/displayapp/screens/settings/SettingChimes.h index a251e95b..e48432c6 100644 --- a/src/displayapp/screens/settings/SettingChimes.h +++ b/src/displayapp/screens/settings/SettingChimes.h @@ -4,6 +4,7 @@ #include <lvgl/lvgl.h> #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include <array> namespace Pinetime { @@ -18,9 +19,19 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: + struct Option { + Controllers::Settings::ChimesOption chimesOption; + const char* name; + }; + static constexpr std::array<Option, 3> options = {{ + {Controllers::Settings::ChimesOption::None, " Off"}, + {Controllers::Settings::ChimesOption::Hours, " Every hour"}, + {Controllers::Settings::ChimesOption::HalfHours, " Every 30 mins"} + }}; + + std::array<lv_obj_t*, options.size()> cbOption; + Controllers::Settings& settingsController; - uint8_t optionsTotal; - lv_obj_t* cbOption[3]; }; } } diff --git a/src/displayapp/screens/settings/SettingDisplay.cpp b/src/displayapp/screens/settings/SettingDisplay.cpp index bf2087ab..e044a85a 100644 --- a/src/displayapp/screens/settings/SettingDisplay.cpp +++ b/src/displayapp/screens/settings/SettingDisplay.cpp @@ -15,7 +15,7 @@ namespace { } } -constexpr std::array<uint16_t, 4> SettingDisplay::options; +constexpr std::array<uint16_t, 6> SettingDisplay::options; SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { @@ -30,7 +30,7 @@ SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime lv_obj_set_pos(container1, 10, 60); lv_obj_set_width(container1, LV_HOR_RES - 20); lv_obj_set_height(container1, LV_VER_RES - 50); - lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + lv_cont_set_layout(container1, LV_LAYOUT_PRETTY_TOP); lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Display timeout"); @@ -46,7 +46,7 @@ SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime char buffer[12]; for (unsigned int i = 0; i < options.size(); i++) { cbOption[i] = lv_checkbox_create(container1, nullptr); - sprintf(buffer, "%3d seconds", options[i] / 1000); + sprintf(buffer, "%2ds", options[i] / 1000); lv_checkbox_set_text(cbOption[i], buffer); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); diff --git a/src/displayapp/screens/settings/SettingDisplay.h b/src/displayapp/screens/settings/SettingDisplay.h index dc56419d..eeddaef8 100644 --- a/src/displayapp/screens/settings/SettingDisplay.h +++ b/src/displayapp/screens/settings/SettingDisplay.h @@ -20,7 +20,7 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: - static constexpr std::array<uint16_t, 4> options = {5000, 15000, 20000, 30000}; + static constexpr std::array<uint16_t, 6> options = {5000, 7000, 10000, 15000, 20000, 30000}; Controllers::Settings& settingsController; lv_obj_t* cbOption[options.size()]; diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index 7acf0c19..1407a98f 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -11,13 +11,36 @@ namespace { constexpr int16_t POS_X_DAY = -72; constexpr int16_t POS_X_MONTH = 0; constexpr int16_t POS_X_YEAR = 72; - constexpr int16_t POS_Y_PLUS = -50; constexpr int16_t POS_Y_TEXT = -6; - constexpr int16_t POS_Y_MINUS = 40; void event_handler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast<SettingSetDate*>(obj->user_data); - screen->HandleButtonPress(obj, event); + if (event == LV_EVENT_CLICKED) { + screen->HandleButtonPress(); + } + } + + void ValueChangedHandler(void* userData) { + auto* screen = static_cast<SettingSetDate*>(userData); + screen->CheckDay(); + } + + int MaximumDayOfMonth(uint8_t month, uint16_t year) { + switch (month) { + case 2: { + if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) { + return 29; + } + return 28; + } + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + } } } @@ -35,164 +58,54 @@ SettingSetDate::SettingSetDate(Pinetime::Applications::DisplayApp* app, Pinetime lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - dayValue = static_cast<int>(dateTimeController.Day()); - lblDay = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(lblDay, "%d", dayValue); - lv_label_set_align(lblDay, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); - lv_obj_set_auto_realign(lblDay, true); - - monthValue = static_cast<int>(dateTimeController.Month()); - lblMonth = lv_label_create(lv_scr_act(), nullptr); - UpdateMonthLabel(); - lv_label_set_align(lblMonth, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblMonth, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); - lv_obj_set_auto_realign(lblMonth, true); - - yearValue = static_cast<int>(dateTimeController.Year()); - if (yearValue < 2021) - yearValue = 2021; - lblYear = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(lblYear, "%d", yearValue); - lv_label_set_align(lblYear, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); - lv_obj_set_auto_realign(lblYear, true); - - btnDayPlus = lv_btn_create(lv_scr_act(), nullptr); - btnDayPlus->user_data = this; - lv_obj_set_size(btnDayPlus, 50, 40); - lv_obj_align(btnDayPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_PLUS); - lv_obj_set_style_local_value_str(btnDayPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); - lv_obj_set_event_cb(btnDayPlus, event_handler); - - btnDayMinus = lv_btn_create(lv_scr_act(), nullptr); - btnDayMinus->user_data = this; - lv_obj_set_size(btnDayMinus, 50, 40); - lv_obj_align(btnDayMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_MINUS); - lv_obj_set_style_local_value_str(btnDayMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); - lv_obj_set_event_cb(btnDayMinus, event_handler); - - btnMonthPlus = lv_btn_create(lv_scr_act(), nullptr); - btnMonthPlus->user_data = this; - lv_obj_set_size(btnMonthPlus, 50, 40); - lv_obj_align(btnMonthPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_PLUS); - lv_obj_set_style_local_value_str(btnMonthPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); - lv_obj_set_event_cb(btnMonthPlus, event_handler); + dayCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + dayCounter.Create(); + dayCounter.SetValue(dateTimeController.Day()); + lv_obj_align(dayCounter.GetObject(), nullptr, LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); - btnMonthMinus = lv_btn_create(lv_scr_act(), nullptr); - btnMonthMinus->user_data = this; - lv_obj_set_size(btnMonthMinus, 50, 40); - lv_obj_align(btnMonthMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_MINUS); - lv_obj_set_style_local_value_str(btnMonthMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); - lv_obj_set_event_cb(btnMonthMinus, event_handler); + monthCounter.EnableMonthMode(); + monthCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + monthCounter.Create(); + monthCounter.SetValue(static_cast<int>(dateTimeController.Month())); + lv_obj_align(monthCounter.GetObject(), nullptr, LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); - btnYearPlus = lv_btn_create(lv_scr_act(), nullptr); - btnYearPlus->user_data = this; - lv_obj_set_size(btnYearPlus, 50, 40); - lv_obj_align(btnYearPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_PLUS); - lv_obj_set_style_local_value_str(btnYearPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); - lv_obj_set_event_cb(btnYearPlus, event_handler); - - btnYearMinus = lv_btn_create(lv_scr_act(), nullptr); - btnYearMinus->user_data = this; - lv_obj_set_size(btnYearMinus, 50, 40); - lv_obj_align(btnYearMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_MINUS); - lv_obj_set_style_local_value_str(btnYearMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); - lv_obj_set_event_cb(btnYearMinus, event_handler); + yearCounter.SetValueChangedEventCallback(this, ValueChangedHandler); + yearCounter.Create(); + yearCounter.SetValue(dateTimeController.Year()); + lv_obj_align(yearCounter.GetObject(), nullptr, LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); btnSetTime = lv_btn_create(lv_scr_act(), nullptr); btnSetTime->user_data = this; lv_obj_set_size(btnSetTime, 120, 48); lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_set_style_local_bg_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x38, 0x38, 0x38)); lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); lv_obj_set_event_cb(btnSetTime, event_handler); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); } SettingSetDate::~SettingSetDate() { lv_obj_clean(lv_scr_act()); } -void SettingSetDate::HandleButtonPress(lv_obj_t* object, lv_event_t event) { - if (event != LV_EVENT_CLICKED) - return; - - if (object == btnDayPlus) { - dayValue++; - if (dayValue > MaximumDayOfMonth()) - dayValue = 1; - lv_label_set_text_fmt(lblDay, "%d", dayValue); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } else if (object == btnDayMinus) { - dayValue--; - if (dayValue < 1) - dayValue = MaximumDayOfMonth(); - lv_label_set_text_fmt(lblDay, "%d", dayValue); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } else if (object == btnMonthPlus) { - monthValue++; - if (monthValue > 12) - monthValue = 1; - UpdateMonthLabel(); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - CheckDay(); - } else if (object == btnMonthMinus) { - monthValue--; - if (monthValue < 1) - monthValue = 12; - UpdateMonthLabel(); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - CheckDay(); - } else if (object == btnYearPlus) { - yearValue++; - lv_label_set_text_fmt(lblYear, "%d", yearValue); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - CheckDay(); - } else if (object == btnYearMinus) { - yearValue--; - lv_label_set_text_fmt(lblYear, "%d", yearValue); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - CheckDay(); - } else if (object == btnSetTime) { - NRF_LOG_INFO("Setting date (manually) to %04d-%02d-%02d", yearValue, monthValue, dayValue); - dateTimeController.SetTime(static_cast<uint16_t>(yearValue), - static_cast<uint8_t>(monthValue), - static_cast<uint8_t>(dayValue), - 0, - dateTimeController.Hours(), - dateTimeController.Minutes(), - dateTimeController.Seconds(), - nrf_rtc_counter_get(portNRF_RTC_REG)); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); - } -} - -int SettingSetDate::MaximumDayOfMonth() const { - switch (monthValue) { - case 2: - if ((((yearValue % 4) == 0) && ((yearValue % 100) != 0)) || ((yearValue % 400) == 0)) - return 29; - return 28; - case 4: - case 6: - case 9: - case 11: - return 30; - default: - return 31; - } +void SettingSetDate::HandleButtonPress() { + const uint16_t yearValue = yearCounter.GetValue(); + const uint8_t monthValue = monthCounter.GetValue(); + const uint8_t dayValue = dayCounter.GetValue(); + NRF_LOG_INFO("Setting date (manually) to %04d-%02d-%02d", yearValue, monthValue, dayValue); + dateTimeController.SetTime(yearValue, + monthValue, + dayValue, + 0, + dateTimeController.Hours(), + dateTimeController.Minutes(), + dateTimeController.Seconds(), + nrf_rtc_counter_get(portNRF_RTC_REG)); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); } void SettingSetDate::CheckDay() { - int maxDay = MaximumDayOfMonth(); - if (dayValue > maxDay) { - dayValue = maxDay; - lv_label_set_text_fmt(lblDay, "%d", dayValue); - lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); - } -} - -void SettingSetDate::UpdateMonthLabel() { - lv_label_set_text_static( - lblMonth, - Pinetime::Controllers::DateTime::MonthShortToStringLow(static_cast<Pinetime::Controllers::DateTime::Months>(monthValue))); + const int maxDay = MaximumDayOfMonth(monthCounter.GetValue(), yearCounter.GetValue()); + dayCounter.SetMax(maxDay); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } diff --git a/src/displayapp/screens/settings/SettingSetDate.h b/src/displayapp/screens/settings/SettingSetDate.h index a1795942..af0d654e 100644 --- a/src/displayapp/screens/settings/SettingSetDate.h +++ b/src/displayapp/screens/settings/SettingSetDate.h @@ -4,6 +4,7 @@ #include <lvgl/lvgl.h> #include "components/datetime/DateTimeController.h" #include "displayapp/screens/Screen.h" +#include "displayapp/widgets/Counter.h" namespace Pinetime { namespace Applications { @@ -13,28 +14,17 @@ namespace Pinetime { SettingSetDate(DisplayApp* app, Pinetime::Controllers::DateTime& dateTimeController); ~SettingSetDate() override; - void HandleButtonPress(lv_obj_t* object, lv_event_t event); + void HandleButtonPress(); + void CheckDay(); private: Controllers::DateTime& dateTimeController; - int dayValue; - int monthValue; - int yearValue; - lv_obj_t* lblDay; - lv_obj_t* lblMonth; - lv_obj_t* lblYear; - lv_obj_t* btnDayPlus; - lv_obj_t* btnDayMinus; - lv_obj_t* btnMonthPlus; - lv_obj_t* btnMonthMinus; - lv_obj_t* btnYearPlus; - lv_obj_t* btnYearMinus; lv_obj_t* btnSetTime; - int MaximumDayOfMonth() const; - void CheckDay(); - void UpdateMonthLabel(); + Widgets::Counter dayCounter = Widgets::Counter(1, 31, jetbrains_mono_bold_20); + Widgets::Counter monthCounter = Widgets::Counter(1, 12, jetbrains_mono_bold_20); + Widgets::Counter yearCounter = Widgets::Counter(1970, 9999, jetbrains_mono_bold_20); }; } } diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index 037611f3..47b786e4 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -5,21 +5,22 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" #include "components/settings/Settings.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; namespace { - constexpr int16_t POS_X_HOURS = -72; - constexpr int16_t POS_X_MINUTES = 0; - constexpr int16_t POS_X_SECONDS = 72; - constexpr int16_t POS_Y_PLUS = -50; - constexpr int16_t POS_Y_TEXT = -6; - constexpr int16_t POS_Y_MINUS = 40; - constexpr int16_t OFS_Y_COLON = -2; + constexpr int16_t POS_Y_TEXT = -7; - void event_handler(lv_obj_t* obj, lv_event_t event) { + void SetTimeEventHandler(lv_obj_t* obj, lv_event_t event) { auto* screen = static_cast<SettingSetTime*>(obj->user_data); - screen->HandleButtonPress(obj, event); + if (event == LV_EVENT_CLICKED) { + screen->SetTime(); + } + } + void ValueChangedHandler(void* userData) { + auto* screen = static_cast<SettingSetTime*>(userData); + screen->UpdateScreen(); } } @@ -27,6 +28,7 @@ SettingSetTime::SettingSetTime(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::DateTime& dateTimeController, Pinetime::Controllers::Settings& settingsController) : Screen(app), dateTimeController {dateTimeController}, settingsController {settingsController} { + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Set current time"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); @@ -34,160 +36,72 @@ SettingSetTime::SettingSetTime(Pinetime::Applications::DisplayApp* app, lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); - lv_label_set_text_static(icon, Symbols::clock); lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - hoursValue = static_cast<int>(dateTimeController.Hours()); - lblHours = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblHours, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(lblHours, "%02d", hoursValue); - lv_label_set_align(lblHours, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); - lv_obj_set_auto_realign(lblHours, true); - - lv_obj_t* lblColon1 = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblColon1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_static(lblColon1, ":"); - lv_label_set_align(lblColon1, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblColon1, lv_scr_act(), LV_ALIGN_CENTER, (POS_X_HOURS + POS_X_MINUTES) / 2, POS_Y_TEXT + OFS_Y_COLON); + lv_obj_t* staticLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(staticLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_static(staticLabel, "00:00:00"); + lv_obj_align(staticLabel, lv_scr_act(), LV_ALIGN_CENTER, 0, POS_Y_TEXT); - minutesValue = static_cast<int>(dateTimeController.Minutes()); - lblMinutes = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblMinutes, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_label_set_align(lblMinutes, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); - lv_obj_set_auto_realign(lblMinutes, true); - - lv_obj_t* lblColon2 = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblColon2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_static(lblColon2, ":"); - lv_label_set_align(lblColon2, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblColon2, lv_scr_act(), LV_ALIGN_CENTER, (POS_X_MINUTES + POS_X_SECONDS) / 2, POS_Y_TEXT + OFS_Y_COLON); + hourCounter.Create(); + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { + hourCounter.EnableTwelveHourMode(); + } + hourCounter.SetValue(dateTimeController.Hours()); + lv_obj_align(hourCounter.GetObject(), nullptr, LV_ALIGN_CENTER, -75, POS_Y_TEXT); + hourCounter.SetValueChangedEventCallback(this, ValueChangedHandler); - lv_obj_t* lblSeconds = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(lblSeconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_static(lblSeconds, "00"); - lv_label_set_align(lblSeconds, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblSeconds, lv_scr_act(), LV_ALIGN_CENTER, POS_X_SECONDS, POS_Y_TEXT); + minuteCounter.Create(); + minuteCounter.SetValue(dateTimeController.Minutes()); + lv_obj_align(minuteCounter.GetObject(), nullptr, LV_ALIGN_CENTER, 0, POS_Y_TEXT); + minuteCounter.SetValueChangedEventCallback(this, ValueChangedHandler); 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_label_set_text_static(lblampm, " "); - lv_label_set_align(lblampm, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, POS_X_SECONDS, POS_Y_PLUS); - - btnHoursPlus = lv_btn_create(lv_scr_act(), nullptr); - btnHoursPlus->user_data = this; - lv_obj_set_size(btnHoursPlus, 50, 40); - lv_obj_align(btnHoursPlus, lv_scr_act(), LV_ALIGN_CENTER, -72, -50); - lv_obj_set_style_local_value_str(btnHoursPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); - lv_obj_set_event_cb(btnHoursPlus, event_handler); - - btnHoursMinus = lv_btn_create(lv_scr_act(), nullptr); - btnHoursMinus->user_data = this; - lv_obj_set_size(btnHoursMinus, 50, 40); - lv_obj_align(btnHoursMinus, lv_scr_act(), LV_ALIGN_CENTER, -72, 40); - lv_obj_set_style_local_value_str(btnHoursMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); - lv_obj_set_event_cb(btnHoursMinus, event_handler); - - btnMinutesPlus = lv_btn_create(lv_scr_act(), nullptr); - btnMinutesPlus->user_data = this; - lv_obj_set_size(btnMinutesPlus, 50, 40); - lv_obj_align(btnMinutesPlus, lv_scr_act(), LV_ALIGN_CENTER, 0, -50); - lv_obj_set_style_local_value_str(btnMinutesPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); - lv_obj_set_event_cb(btnMinutesPlus, event_handler); - - btnMinutesMinus = lv_btn_create(lv_scr_act(), nullptr); - btnMinutesMinus->user_data = this; - lv_obj_set_size(btnMinutesMinus, 50, 40); - lv_obj_align(btnMinutesMinus, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); - lv_obj_set_style_local_value_str(btnMinutesMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); - lv_obj_set_event_cb(btnMinutesMinus, event_handler); + lv_obj_align(lblampm, lv_scr_act(), LV_ALIGN_CENTER, 75, -50); btnSetTime = lv_btn_create(lv_scr_act(), nullptr); btnSetTime->user_data = this; - lv_obj_set_size(btnSetTime, 120, 48); + lv_obj_set_size(btnSetTime, 120, 50); lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); - lv_obj_set_event_cb(btnSetTime, event_handler); + lv_obj_set_style_local_bg_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_value_color(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DISABLED, LV_COLOR_GRAY); + lv_obj_set_event_cb(btnSetTime, SetTimeEventHandler); - SetHourLabels(); + UpdateScreen(); + lv_obj_set_state(btnSetTime, LV_STATE_DISABLED); } SettingSetTime::~SettingSetTime() { lv_obj_clean(lv_scr_act()); } -void SettingSetTime::SetHourLabels() { +void SettingSetTime::UpdateScreen() { if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { - switch (hoursValue) { - case 0: - lv_label_set_text_static(lblHours, "12"); - lv_label_set_text_static(lblampm, "AM"); - break; - case 1 ... 11: - lv_label_set_text_fmt(lblHours, "%02d", hoursValue); - lv_label_set_text_static(lblampm, "AM"); - break; - case 12: - lv_label_set_text_static(lblHours, "12"); - lv_label_set_text_static(lblampm, "PM"); - break; - case 13 ... 23: - lv_label_set_text_fmt(lblHours, "%02d", hoursValue - 12); - lv_label_set_text_static(lblampm, "PM"); - break; + if (hourCounter.GetValue() >= 12) { + lv_label_set_text_static(lblampm, "PM"); + } else { + lv_label_set_text_static(lblampm, "AM"); } - } else { - lv_label_set_text_fmt(lblHours, "%02d", hoursValue); } + lv_obj_set_state(btnSetTime, LV_STATE_DEFAULT); } -void SettingSetTime::HandleButtonPress(lv_obj_t* object, lv_event_t event) { - if (event != LV_EVENT_CLICKED) - return; - - if (object == btnHoursPlus) { - hoursValue++; - if (hoursValue > 23) { - hoursValue = 0; - } - SetHourLabels(); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } else if (object == btnHoursMinus) { - hoursValue--; - if (hoursValue < 0) { - hoursValue = 23; - } - SetHourLabels(); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } else if (object == btnMinutesPlus) { - minutesValue++; - if (minutesValue > 59) { - minutesValue = 0; - } - lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } else if (object == btnMinutesMinus) { - minutesValue--; - if (minutesValue < 0) { - minutesValue = 59; - } - lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } else if (object == btnSetTime) { - NRF_LOG_INFO("Setting time (manually) to %02d:%02d:00", hoursValue, minutesValue); - dateTimeController.SetTime(dateTimeController.Year(), - static_cast<uint8_t>(dateTimeController.Month()), - dateTimeController.Day(), - static_cast<uint8_t>(dateTimeController.DayOfWeek()), - static_cast<uint8_t>(hoursValue), - static_cast<uint8_t>(minutesValue), - 0, - nrf_rtc_counter_get(portNRF_RTC_REG)); - lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); - } +void SettingSetTime::SetTime() { + const int hoursValue = hourCounter.GetValue(); + const int minutesValue = minuteCounter.GetValue(); + NRF_LOG_INFO("Setting time (manually) to %02d:%02d:00", hoursValue, minutesValue); + dateTimeController.SetTime(dateTimeController.Year(), + static_cast<uint8_t>(dateTimeController.Month()), + dateTimeController.Day(), + static_cast<uint8_t>(dateTimeController.DayOfWeek()), + static_cast<uint8_t>(hoursValue), + static_cast<uint8_t>(minutesValue), + 0, + nrf_rtc_counter_get(portNRF_RTC_REG)); + lv_obj_set_state(btnSetTime, LV_STATE_DISABLED); } diff --git a/src/displayapp/screens/settings/SettingSetTime.h b/src/displayapp/screens/settings/SettingSetTime.h index d02c332e..e0b42bdd 100644 --- a/src/displayapp/screens/settings/SettingSetTime.h +++ b/src/displayapp/screens/settings/SettingSetTime.h @@ -4,6 +4,7 @@ #include <lvgl/lvgl.h> #include "components/datetime/DateTimeController.h" #include "components/settings/Settings.h" +#include "displayapp/widgets/Counter.h" #include "displayapp/screens/Screen.h" namespace Pinetime { @@ -16,24 +17,17 @@ namespace Pinetime { Pinetime::Controllers::Settings& settingsController); ~SettingSetTime() override; - void HandleButtonPress(lv_obj_t* object, lv_event_t event); + void SetTime(); + void UpdateScreen(); private: Controllers::DateTime& dateTimeController; Controllers::Settings& settingsController; - void SetHourLabels(); - - int hoursValue; - int minutesValue; - lv_obj_t* lblHours; - lv_obj_t* lblMinutes; lv_obj_t* lblampm; - lv_obj_t* btnHoursPlus; - lv_obj_t* btnHoursMinus; - lv_obj_t* btnMinutesPlus; - lv_obj_t* btnMinutesMinus; lv_obj_t* btnSetTime; + Widgets::Counter hourCounter = Widgets::Counter(0, 23, jetbrains_mono_42); + Widgets::Counter minuteCounter = Widgets::Counter(0, 59, jetbrains_mono_42); }; } } diff --git a/src/displayapp/screens/settings/SettingShakeThreshold.cpp b/src/displayapp/screens/settings/SettingShakeThreshold.cpp index aac1eaff..de46f7de 100644 --- a/src/displayapp/screens/settings/SettingShakeThreshold.cpp +++ b/src/displayapp/screens/settings/SettingShakeThreshold.cpp @@ -3,6 +3,7 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" +#include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -123,8 +124,7 @@ void SettingShakeThreshold::UpdateSelected(lv_obj_t* object, lv_event_t event) { vCalTime = xTaskGetTickCount(); lv_label_set_text_static(calLabel, "Ready!"); lv_obj_set_click(positionArc, false); - lv_obj_set_style_local_bg_color(calButton, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); - lv_obj_set_style_local_bg_color(calButton, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_COLOR_MAKE(0x0, 0xb0, 0x0)); + lv_obj_set_style_local_bg_color(calButton, LV_BTN_PART_MAIN, LV_STATE_CHECKED, Colors::highlight); } else if (lv_btn_get_state(calButton) == LV_BTN_STATE_RELEASED) { calibrating = 0; lv_obj_set_click(positionArc, true); diff --git a/src/displayapp/screens/settings/SettingSteps.cpp b/src/displayapp/screens/settings/SettingSteps.cpp index e92600c2..af5bd6e9 100644 --- a/src/displayapp/screens/settings/SettingSteps.cpp +++ b/src/displayapp/screens/settings/SettingSteps.cpp @@ -17,7 +17,6 @@ SettingSteps::SettingSteps(Pinetime::Applications::DisplayApp* app, Pinetime::Co lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); - // lv_obj_set_style_local_bg_color(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10); lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5); diff --git a/src/displayapp/screens/settings/SettingTimeFormat.h b/src/displayapp/screens/settings/SettingTimeFormat.h index 818edf0c..01ca2c9b 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.h +++ b/src/displayapp/screens/settings/SettingTimeFormat.h @@ -20,7 +20,7 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: - static constexpr std::array<const char*, 2> options = {" 12-hour", " 24-hour"}; + static constexpr std::array<const char*, 2> options = {"12-hour", "24-hour"}; Controllers::Settings& settingsController; lv_obj_t* cbOption[options.size()]; }; diff --git a/src/displayapp/screens/settings/SettingWakeUp.cpp b/src/displayapp/screens/settings/SettingWakeUp.cpp index 4a4b60f8..59275e2f 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.cpp +++ b/src/displayapp/screens/settings/SettingWakeUp.cpp @@ -42,7 +42,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: optionsTotal = 0; cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Single Tap"); + lv_checkbox_set_text_static(cbOption[optionsTotal], "Single Tap"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)) { @@ -50,7 +50,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: } optionsTotal++; cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Double Tap"); + lv_checkbox_set_text_static(cbOption[optionsTotal], "Double Tap"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) { @@ -58,7 +58,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: } optionsTotal++; cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Raise Wrist"); + lv_checkbox_set_text_static(cbOption[optionsTotal], "Raise Wrist"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) { @@ -66,7 +66,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime:: } optionsTotal++; cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Shake Wake"); + lv_checkbox_set_text_static(cbOption[optionsTotal], "Shake Wake"); cbOption[optionsTotal]->user_data = this; lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake)) { diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp index 8cbbcf7b..788dd8e8 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.cpp +++ b/src/displayapp/screens/settings/SettingWatchFace.cpp @@ -38,7 +38,7 @@ bool SettingWatchFace::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } std::unique_ptr<Screen> SettingWatchFace::CreateScreen1() { - std::array<const char*, 4> watchfaces {" Digital face", " Analog face", " PineTimeStyle", " Terminal"}; + std::array<const char*, 4> watchfaces {"Digital face", "Analog face", "PineTimeStyle", "Terminal"}; return std::make_unique<Screens::CheckboxList>(0, 2, app, settingsController, title, symbol, &Controllers::Settings::SetClockFace, &Controllers::Settings::GetClockFace, @@ -46,7 +46,7 @@ std::unique_ptr<Screen> SettingWatchFace::CreateScreen1() { } std::unique_ptr<Screen> SettingWatchFace::CreateScreen2() { - std::array<const char*, 4> watchfaces {" Infineat face", "", "", ""}; + std::array<const char*, 4> watchfaces {"Infineat face", "", "", ""}; return std::make_unique<Screens::CheckboxList>(1, 2, app, settingsController, title, symbol, &Controllers::Settings::SetClockFace, &Controllers::Settings::GetClockFace, diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index a91b8f77..ffa01d18 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -1,33 +1,27 @@ #include "displayapp/screens/settings/Settings.h" #include <lvgl/lvgl.h> -#include <array> -#include "displayapp/screens/List.h" +#include <functional> #include "displayapp/Apps.h" #include "displayapp/DisplayApp.h" -#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; +constexpr std::array<List::Applications, Settings::entries.size()> Settings::entries; + +auto Settings::CreateScreenList() const { + std::array<std::function<std::unique_ptr<Screen>()>, nScreens> screens; + for (size_t i = 0; i < screens.size(); i++) { + screens[i] = [this, i]() -> std::unique_ptr<Screen> { + return CreateScreen(i); + }; + } + return screens; +} + Settings::Settings(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController}, - screens {app, - settingsController.GetSettingsMenu(), - { - [this]() -> std::unique_ptr<Screen> { - return CreateScreen1(); - }, - [this]() -> std::unique_ptr<Screen> { - return CreateScreen2(); - }, - [this]() -> std::unique_ptr<Screen> { - return CreateScreen3(); - }, - [this]() -> std::unique_ptr<Screen> { - return CreateScreen4(); - }, - }, - Screens::ScreenListModes::UpDown} { + screens {app, settingsController.GetSettingsMenu(), CreateScreenList(), Screens::ScreenListModes::UpDown} { } Settings::~Settings() { @@ -38,48 +32,11 @@ bool Settings::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return screens.OnTouchEvent(event); } -std::unique_ptr<Screen> Settings::CreateScreen1() { - std::array<Screens::List::Applications, 4> applications {{ - {Symbols::sun, "Display", Apps::SettingDisplay}, - {Symbols::eye, "Wake Up", Apps::SettingWakeUp}, - {Symbols::clock, "Time format", Apps::SettingTimeFormat}, - {Symbols::home, "Watch face", Apps::SettingWatchFace}, - }}; - - return std::make_unique<Screens::List>(0, 4, app, settingsController, applications); -} - -std::unique_ptr<Screen> Settings::CreateScreen2() { - std::array<Screens::List::Applications, 4> applications {{ - {Symbols::shoe, "Steps", Apps::SettingSteps}, - {Symbols::clock, "Set date", Apps::SettingSetDate}, - {Symbols::clock, "Set time", Apps::SettingSetTime}, - {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, - }}; - - return std::make_unique<Screens::List>(1, 4, app, settingsController, applications); -} - -std::unique_ptr<Screen> Settings::CreateScreen3() { - - std::array<Screens::List::Applications, 4> applications {{ - {Symbols::clock, "Chimes", Apps::SettingChimes}, - {Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold}, - {Symbols::check, "Firmware", Apps::FirmwareValidation}, - {Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth}, - }}; - - return std::make_unique<Screens::List>(2, 4, app, settingsController, applications); -} - -std::unique_ptr<Screen> Settings::CreateScreen4() { - - std::array<Screens::List::Applications, 4> applications {{ - {Symbols::list, "About", Apps::SysInfo}, - {Symbols::none, "None", Apps::None}, - {Symbols::none, "None", Apps::None}, - {Symbols::none, "None", Apps::None}, - }}; +std::unique_ptr<Screen> Settings::CreateScreen(unsigned int screenNum) const { + std::array<List::Applications, entriesPerScreen> screens; + for (int i = 0; i < entriesPerScreen; i++) { + screens[i] = entries[screenNum * entriesPerScreen + i]; + } - return std::make_unique<Screens::List>(3, 4, app, settingsController, applications); + return std::make_unique<Screens::List>(screenNum, nScreens, app, settingsController, screens); } diff --git a/src/displayapp/screens/settings/Settings.h b/src/displayapp/screens/settings/Settings.h index be090075..a86db44f 100644 --- a/src/displayapp/screens/settings/Settings.h +++ b/src/displayapp/screens/settings/Settings.h @@ -1,8 +1,11 @@ #pragma once -#include <cstdint> +#include <array> +#include <memory> #include "displayapp/screens/Screen.h" #include "displayapp/screens/ScreenList.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/List.h" namespace Pinetime { @@ -17,14 +20,38 @@ namespace Pinetime { bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override; private: - Controllers::Settings& settingsController; + auto CreateScreenList() const; + std::unique_ptr<Screen> CreateScreen(unsigned int screenNum) const; - ScreenList<4> screens; + Controllers::Settings& settingsController; - std::unique_ptr<Screen> CreateScreen1(); - std::unique_ptr<Screen> CreateScreen2(); - std::unique_ptr<Screen> CreateScreen3(); - std::unique_ptr<Screen> CreateScreen4(); + static constexpr int entriesPerScreen = 4; + + // Increment this when more space is needed + static constexpr int nScreens = 4; + + static constexpr std::array<List::Applications, entriesPerScreen * nScreens> entries {{ + {Symbols::sun, "Display", Apps::SettingDisplay}, + {Symbols::eye, "Wake Up", Apps::SettingWakeUp}, + {Symbols::clock, "Time format", Apps::SettingTimeFormat}, + {Symbols::home, "Watch face", Apps::SettingWatchFace}, + + {Symbols::shoe, "Steps", Apps::SettingSteps}, + {Symbols::clock, "Set date", Apps::SettingSetDate}, + {Symbols::clock, "Set time", Apps::SettingSetTime}, + {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, + + {Symbols::clock, "Chimes", Apps::SettingChimes}, + {Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold}, + {Symbols::check, "Firmware", Apps::FirmwareValidation}, + {Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth}, + + {Symbols::list, "About", Apps::SysInfo}, + {Symbols::none, "None", Apps::None}, + {Symbols::none, "None", Apps::None}, + {Symbols::none, "None", Apps::None}, + }}; + ScreenList<nScreens> screens; }; } } |