diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 24a826072f..0c876b2a1d 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -17,6 +17,8 @@ namespace Pinetime { RaiseWrist = 2, Shake = 3, }; + enum class BatteryPercentage : u_int8_t { ON, OFF }; + enum class BatteryColor : u_int8_t { ON, OFF }; enum class Colors : uint8_t { White, Silver, @@ -41,6 +43,10 @@ namespace Pinetime { Colors ColorBar = Colors::Teal; Colors ColorBG = Colors::Black; }; + struct DigitalWatchStyle { + BatteryPercentage Percentage = BatteryPercentage::OFF; + BatteryColor Color = BatteryColor::OFF; + }; Settings(Pinetime::Controllers::FS& fs); @@ -94,6 +100,26 @@ namespace Pinetime { return settings.PTS.ColorBG; }; + void SetDWSBatteryPercentageStatus(BatteryPercentage status) { + if (status != settings.DWS.Percentage) { + settingsChanged = true; + } + settings.DWS.Percentage = status; + }; + BatteryPercentage GetDWSBatteryPercentageStatus() const { + return settings.DWS.Percentage; + }; + + void SetDWSBatteryColorStatus(BatteryColor status) { + if (status != settings.DWS.Color) { + settingsChanged = true; + } + settings.DWS.Color = status; + }; + BatteryColor GetDWSBatteryColorStatus() const { + return settings.DWS.Color; + }; + void SetAppMenu(uint8_t menu) { appMenu = menu; }; @@ -213,7 +239,7 @@ namespace Pinetime { private: Pinetime::Controllers::FS& fs; - static constexpr uint32_t settingsVersion = 0x0003; + static constexpr uint32_t settingsVersion = 0x0004; struct SettingsData { uint32_t version = settingsVersion; uint32_t stepsGoal = 10000; @@ -227,6 +253,8 @@ namespace Pinetime { PineTimeStyle PTS; + DigitalWatchStyle DWS; + std::bitset<4> wakeUpMode {0}; uint16_t shakeWakeThreshold = 150; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; diff --git a/src/displayapp/screens/BatteryIcon.cpp b/src/displayapp/screens/BatteryIcon.cpp index 08aaab70f1..ecffc9408f 100644 --- a/src/displayapp/screens/BatteryIcon.cpp +++ b/src/displayapp/screens/BatteryIcon.cpp @@ -1,28 +1,53 @@ #include "displayapp/screens/BatteryIcon.h" #include +#include #include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; const char* BatteryIcon::GetBatteryIcon(uint8_t batteryPercent) { - if (batteryPercent > 87) + if (batteryPercent > 87) { return Symbols::batteryFull; - if (batteryPercent > 62) + } + if (batteryPercent > 62) { return Symbols::batteryThreeQuarter; - if (batteryPercent > 37) + } + if (batteryPercent > 37) { return Symbols::batteryHalf; - if (batteryPercent > 12) + } + if (batteryPercent > 12) { return Symbols::batteryOneQuarter; + } return Symbols::batteryEmpty; } +const lv_color_t BatteryIcon::GetBatteryColor(uint8_t batteryPercent) { + if (batteryPercent > 75) { + return LV_COLOR_GREEN; + } + if (batteryPercent > 50) { + return LV_COLOR_YELLOW; + } + if (batteryPercent > 25) { + return LV_COLOR_ORANGE; + } + return LV_COLOR_RED; +} + +const lv_color_t BatteryIcon::GetDefaultBatteryColor(uint8_t batteryPercent) { + if (batteryPercent == 100) { + return LV_COLOR_GREEN; + } + return LV_COLOR_WHITE; +} + const char* BatteryIcon::GetUnknownIcon() { return Symbols::batteryEmpty; } const char* BatteryIcon::GetPlugIcon(bool isCharging) { - if (isCharging) + if (isCharging) { return Symbols::plug; - else - return ""; + } + return ""; } diff --git a/src/displayapp/screens/BatteryIcon.h b/src/displayapp/screens/BatteryIcon.h index bec2e4e059..c46b7904aa 100644 --- a/src/displayapp/screens/BatteryIcon.h +++ b/src/displayapp/screens/BatteryIcon.h @@ -1,5 +1,6 @@ #pragma once #include +#include namespace Pinetime { namespace Applications { @@ -8,6 +9,8 @@ namespace Pinetime { public: static const char* GetUnknownIcon(); static const char* GetBatteryIcon(uint8_t batteryPercent); + static const lv_color_t GetBatteryColor(uint8_t batteryPercent); + static const lv_color_t GetDefaultBatteryColor(uint8_t batteryPercent); static const char* GetPlugIcon(bool isCharging); }; } diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 59bde83996..1bbdb15e49 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -15,6 +15,13 @@ #include "components/settings/Settings.h" using namespace Pinetime::Applications::Screens; +namespace { + void event_handler(lv_obj_t* obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); + screen->UpdateSelected(obj, event); + } +} + WatchFaceDigital::WatchFaceDigital(DisplayApp* app, Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, @@ -37,10 +44,14 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_label_set_text_static(batteryIcon, Symbols::batteryFull); lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); + batteryValue = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(batteryValue, ""); + lv_obj_align(batteryValue, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); + 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, LV_ALIGN_OUT_LEFT_MID, -5, 0); + lv_obj_align(batteryPlug, batteryValue, 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)); @@ -92,6 +103,66 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_label_set_text_static(stepIcon, Symbols::shoe); lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); + container1 = lv_cont_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(container1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + 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); + lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_pos(container1, 10, 10); + lv_obj_set_width(container1, LV_HOR_RES - 20); + lv_obj_set_height(container1, LV_VER_RES - 20); + + btnSet = lv_btn_create(container1, nullptr); + btnSet->user_data = this; + lv_obj_set_height(btnSet, 150); + lv_obj_set_width(btnSet, 150); + lv_obj_align(btnSet, container1, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_radius(btnSet, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 30); + lv_obj_set_style_local_bg_opa(btnSet, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_event_cb(btnSet, event_handler); + lbl_btnSet = lv_label_create(btnSet, nullptr); + lv_obj_set_style_local_text_font(lbl_btnSet, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); + lv_label_set_text_static(lbl_btnSet, Symbols::settings); + lv_obj_set_hidden(btnSet, true); + + settingsTitle = lv_label_create(container1, nullptr); + lv_label_set_text_static(settingsTitle, "Display Settings"); + lv_label_set_align(settingsTitle, LV_LABEL_ALIGN_CENTER); + lv_obj_align(settingsTitle, container1, LV_ALIGN_IN_TOP_MID, 0, 15); + lv_obj_set_hidden(settingsTitle, true); + + optionsTotal = 0; + cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text_static(cbOption[optionsTotal], " Show Percent"); + cbOption[optionsTotal]->user_data = this; + lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); + if (settingsController.GetDWSBatteryPercentageStatus() == Controllers::Settings::BatteryPercentage::ON) { + lv_checkbox_set_checked(cbOption[optionsTotal], true); + } + lv_obj_align(cbOption[optionsTotal], settingsTitle, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); + lv_obj_set_hidden(cbOption[optionsTotal], true); + optionsTotal++; + + cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text_static(cbOption[optionsTotal], " Color Icon"); + cbOption[optionsTotal]->user_data = this; + lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); + if (settingsController.GetDWSBatteryColorStatus() == Controllers::Settings::BatteryColor::ON) { + lv_checkbox_set_checked(cbOption[optionsTotal], true); + } + lv_obj_align(cbOption[optionsTotal], cbOption[optionsTotal-1], LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5); + lv_obj_set_hidden(cbOption[optionsTotal], true); + optionsTotal++; + + btnClose = lv_btn_create(container1, nullptr); + btnClose->user_data = this; + lv_obj_set_size(btnClose, 60, 60); + lv_obj_align(btnClose, container1, LV_ALIGN_IN_BOTTOM_MID, 0, -5); + lv_obj_set_style_local_value_str(btnClose, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "X"); + lv_obj_set_event_cb(btnClose, event_handler); + lv_obj_set_hidden(btnClose, true); + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); } @@ -110,11 +181,19 @@ void WatchFaceDigital::Refresh() { batteryPercentRemaining = batteryController.PercentRemaining(); if (batteryPercentRemaining.IsUpdated()) { auto batteryPercent = batteryPercentRemaining.Get(); - if (batteryPercent == 100) { - lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + + if (settingsController.GetDWSBatteryColorStatus() == Controllers::Settings::BatteryColor::ON) { + lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, BatteryIcon::GetBatteryColor(batteryPercent)); } else { - lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, BatteryIcon::GetDefaultBatteryColor(batteryPercent)); } + + if (settingsController.GetDWSBatteryPercentageStatus() == Controllers::Settings::BatteryPercentage::ON) { + lv_label_set_text_fmt(batteryValue, "%lu%%", batteryPercent); + } else { + lv_label_set_text_static(batteryValue, ""); + } + lv_label_set_text_static(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); } @@ -124,6 +203,7 @@ void WatchFaceDigital::Refresh() { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleRadioEnabled.Get(), bleState.Get())); } lv_obj_realign(batteryIcon); + lv_obj_realign(batteryValue); lv_obj_realign(batteryPlug); lv_obj_realign(bleIcon); @@ -211,4 +291,90 @@ void WatchFaceDigital::Refresh() { lv_obj_realign(stepValue); lv_obj_realign(stepIcon); } + + if (!lv_obj_get_hidden(btnSet)) { + if ((savedTick > 0) && (lv_tick_get() - savedTick > 3000)) { + lv_obj_set_hidden(btnSet, true); + savedTick = 0; + } + } +} + +bool WatchFaceDigital::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnClose)) { + lv_obj_set_hidden(btnSet, false); + savedTick = lv_tick_get(); + return true; + } + return false; +} + +bool WatchFaceDigital::OnButtonPushed() { + if (!lv_obj_get_hidden(btnClose)) { + CloseMenu(); + return true; + } + return false; +} + +void WatchFaceDigital::CloseMenu() { + settingsController.SaveSettings(); + HideSettingsMenuItems(true); +} + +void WatchFaceDigital::HideSettingsMenuItems(bool visible) { + lv_obj_set_hidden(btnClose, visible); + lv_obj_set_hidden(settingsTitle, visible); + for (int index = 0; index < optionsTotal; ++index) { + lv_obj_set_hidden(cbOption[index], visible); + } + lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); +} + +void WatchFaceDigital::UpdateSelected(lv_obj_t* object, lv_event_t event) { + if (event == LV_EVENT_VALUE_CHANGED) { + int index = 0; + for (; index < optionsTotal; ++index) { + if (cbOption[index] == object) { + break; + } + } + + batteryPercentRemaining = batteryController.PercentRemaining(); + auto batteryPercent = batteryPercentRemaining.Get(); + + if (index == 0) { + if (settingsController.GetDWSBatteryPercentageStatus() == Controllers::Settings::BatteryPercentage::ON) { + settingsController.SetDWSBatteryPercentageStatus(Controllers::Settings::BatteryPercentage::OFF); + lv_checkbox_set_checked(cbOption[index], false); + lv_label_set_text_static(batteryValue, ""); + } else { + settingsController.SetDWSBatteryPercentageStatus(Controllers::Settings::BatteryPercentage::ON); + lv_checkbox_set_checked(cbOption[index], true); + lv_label_set_text_fmt(batteryValue, "%lu%%", batteryPercent); + } + }; + if (index == 1) { + if (settingsController.GetDWSBatteryColorStatus() == Controllers::Settings::BatteryColor::ON) { + settingsController.SetDWSBatteryColorStatus(Controllers::Settings::BatteryColor::OFF); + lv_checkbox_set_checked(cbOption[index], false); + lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, BatteryIcon::GetDefaultBatteryColor(batteryPercent)); + } else { + settingsController.SetDWSBatteryColorStatus(Controllers::Settings::BatteryColor::ON); + lv_checkbox_set_checked(cbOption[index], true); + lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, BatteryIcon::GetBatteryColor(batteryPercent)); + } + }; + } + + if (event == LV_EVENT_CLICKED) { + if (object == btnClose) { + CloseMenu(); + } + if (object == btnSet) { + lv_obj_set_hidden(btnSet, true); + HideSettingsMenuItems(false); + lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + } + } } diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index d33434c07b..fcc2832401 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -35,6 +35,10 @@ namespace Pinetime { void Refresh() override; + bool OnTouchEvent(TouchEvents event) override; + bool OnButtonPushed() override; + void UpdateSelected(lv_obj_t *object, lv_event_t event); + private: uint8_t displayedHour = -1; uint8_t displayedMinute = -1; @@ -61,6 +65,7 @@ namespace Pinetime { lv_obj_t* backgroundLabel; lv_obj_t* batteryIcon; lv_obj_t* bleIcon; + lv_obj_t* batteryValue; lv_obj_t* batteryPlug; lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatValue; @@ -68,6 +73,15 @@ namespace Pinetime { lv_obj_t* stepValue; lv_obj_t* notificationIcon; + uint32_t savedTick = 0; + uint8_t optionsTotal; + lv_obj_t* container1; + lv_obj_t* settingsTitle; + lv_obj_t* cbOption[2]; + lv_obj_t* btnSet; + lv_obj_t* lbl_btnSet; + lv_obj_t* btnClose; + Controllers::DateTime& dateTimeController; Controllers::Battery& batteryController; Controllers::Ble& bleController; @@ -76,6 +90,9 @@ namespace Pinetime { Controllers::HeartRateController& heartRateController; Controllers::MotionController& motionController; + void CloseMenu(); + void HideSettingsMenuItems(bool visible); + lv_task_t* taskRefresh; }; }