diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07eabe11c0..652bd50a58 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -436,6 +436,7 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingPineTimeStyle.cpp displayapp/screens/settings/SettingSetDate.cpp displayapp/screens/settings/SettingSetTime.cpp + displayapp/screens/settings/SettingStopWatch.cpp ## Watch faces displayapp/icons/bg_clock.c diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 871ff3b6cf..e88ff2887b 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -20,6 +20,7 @@ namespace Pinetime { enum class Colors : uint8_t { White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Cyan, Teal, Blue, Navy, Magenta, Purple, Orange }; + enum class StopWatchSleepMode : uint8_t { Enable, Disable }; struct PineTimeStyle { Colors ColorTime = Colors::Teal; Colors ColorBar = Colors::Teal; @@ -160,6 +161,15 @@ namespace Pinetime { uint32_t GetStepsGoal() const { return settings.stepsGoal; }; + void SetStopWatchSleepMode(StopWatchSleepMode mode) { + if ( mode != settings.stopWatchSleepMode ) { + settingsChanged = true; + } + settings.stopWatchSleepMode = mode; + }; + + StopWatchSleepMode GetStopWatchSleepMode() const { return settings.stopWatchSleepMode; }; + private: Pinetime::Controllers::FS& fs; @@ -179,6 +189,8 @@ namespace Pinetime { std::bitset<3> wakeUpMode {0}; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; + + StopWatchSleepMode stopWatchSleepMode = StopWatchSleepMode::Disable; }; SettingsData settings; diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index d340efee37..1581626044 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -35,6 +35,7 @@ namespace Pinetime { SettingPineTimeStyle, SettingSetDate, SettingSetTime, + SettingStopWatch, Error, }; } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 6e5cb5763d..9be2129c68 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -47,6 +47,7 @@ #include "displayapp/screens/settings/SettingPineTimeStyle.h" #include "displayapp/screens/settings/SettingSetDate.h" #include "displayapp/screens/settings/SettingSetTime.h" +#include "displayapp/screens/settings/SettingStopWatch.h" #include "libs/lv_conf.h" @@ -378,6 +379,10 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this, settingsController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; + case Apps::SettingStopWatch: + currentScreen = std::make_unique(this, settingsController); + ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); + break; case Apps::SettingSetDate: currentScreen = std::make_unique(this, dateTimeController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); @@ -404,7 +409,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); break; case Apps::StopWatch: - currentScreen = std::make_unique(this, *systemTask); + currentScreen = std::make_unique(this, *systemTask, settingsController); break; case Apps::Twos: currentScreen = std::make_unique(this); diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 9b27a89db2..dbe6a7a826 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -6,10 +6,12 @@ #include "projdefs.h" #include "FreeRTOSConfig.h" #include "task.h" +#include "components/settings/Settings.h" #include using namespace Pinetime::Applications::Screens; +using namespace Pinetime::Controllers; // Anonymous namespace for local functions namespace { @@ -45,9 +47,10 @@ static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) { stopWatch->stopLapBtnEventHandler(event); } -StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask) +StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask, Controllers::Settings& settingsController) : Screen(app), systemTask {systemTask}, + settingsController {settingsController}, currentState {States::Init}, startTime {}, oldTimeElapsed {}, @@ -136,7 +139,9 @@ void StopWatch::start() { lv_label_set_text(txtStopLap, Symbols::lapsFlag); startTime = xTaskGetTickCount(); currentState = States::Running; - systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + if (settingsController.GetStopWatchSleepMode() == Settings::StopWatchSleepMode::Disable) { + systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + } } void StopWatch::pause() { @@ -195,7 +200,7 @@ void StopWatch::stopLapBtnEventHandler(lv_event_t event) { } bool StopWatch::OnButtonPushed() { - if (currentState == States::Running) { + if (currentState == States::Running && settingsController.GetStopWatchSleepMode() == Settings::StopWatchSleepMode::Disable) { pause(); return true; } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 25634e9236..7bca0a8a46 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -10,82 +10,90 @@ #include #include "systemtask/SystemTask.h" -namespace Pinetime::Applications::Screens { +namespace Pinetime { - enum class States { Init, Running, Halted }; + namespace Controllers { + class Settings; + } - struct TimeSeparated_t { - int mins; - int secs; - int hundredths; - }; + namespace Applications::Screens { - // A simple buffer to hold the latest two laps - template struct LapTextBuffer_t { - LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} { - } + enum class States { Init, Running, Halted }; - void addLaps(const TimeSeparated_t& timeVal) { - head++; - head %= capacity; - buffer[head] = timeVal; + struct TimeSeparated_t { + int mins; + int secs; + int hundredths; + }; - if (currentSize < capacity) { - currentSize++; + // A simple buffer to hold the latest two laps + template struct LapTextBuffer_t { + LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} { } - } - - 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]); + + 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; } - return nullptr; - } - - private: - std::array buffer; - uint8_t currentSize; - uint8_t capacity; - int8_t head; - }; - - class StopWatch : public Screen { - public: - StopWatch(DisplayApp* app, System::SystemTask& systemTask); - ~StopWatch() override; - void Refresh() override; - - void playPauseBtnEventHandler(lv_event_t event); - void stopLapBtnEventHandler(lv_event_t event); - bool OnButtonPushed() override; - - void reset(); - void start(); - void pause(); - - private: - Pinetime::System::SystemTask& systemTask; - TickType_t timeElapsed; - States currentState; - TickType_t startTime; - TickType_t oldTimeElapsed; - TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs - LapTextBuffer_t<2> lapBuffer; - int lapNr = 0; - lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; - lv_obj_t *lapOneText, *lapTwoText; - - lv_task_t* taskRefresh; - }; + + private: + std::array buffer; + uint8_t currentSize; + uint8_t capacity; + int8_t head; + }; + + class StopWatch : public Screen { + public: + StopWatch(DisplayApp* app, System::SystemTask& systemTask, Controllers::Settings& settingsController); + ~StopWatch() override; + void Refresh() override; + + void playPauseBtnEventHandler(lv_event_t event); + void stopLapBtnEventHandler(lv_event_t event); + bool OnButtonPushed() override; + + void reset(); + void start(); + void pause(); + + private: + Pinetime::System::SystemTask& systemTask; + Controllers::Settings& settingsController; + TickType_t timeElapsed; + States currentState; + TickType_t startTime; + TickType_t oldTimeElapsed; + TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs + LapTextBuffer_t<2> lapBuffer; + int lapNr = 0; + lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; + lv_obj_t *lapOneText, *lapTwoText; + + lv_task_t* taskRefresh; + }; + } } diff --git a/src/displayapp/screens/settings/SettingStopWatch.cpp b/src/displayapp/screens/settings/SettingStopWatch.cpp new file mode 100644 index 0000000000..1cbfaa149a --- /dev/null +++ b/src/displayapp/screens/settings/SettingStopWatch.cpp @@ -0,0 +1,96 @@ +#include "SettingStopWatch.h" +#include +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + static void event_handler(lv_obj_t* obj, lv_event_t event) { + SettingStopWatch* screen = static_cast(obj->user_data); + screen->UpdateSelected(obj, event); + } +} + +SettingStopWatch::SettingStopWatch(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) + : Screen(app), settingsController {settingsController} { + + lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); + + 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, 140); + 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_obj_t* title = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(title, + "Stopwatch\n" + "sleep mode"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); + + 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); + + lv_obj_t* description = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(description, true); + lv_label_set_text_static(description, + "#444444 Sleep screen while#\n" + "#444444 the stopwatch#\n" + "#444444 is running.#"); + lv_label_set_align(description, LV_LABEL_ALIGN_CENTER); + lv_obj_align(description, lv_scr_act(), LV_ALIGN_CENTER, 0, -20); + + optionsTotal = 0; + cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text_static(cbOption[optionsTotal], " Disable"); + cbOption[optionsTotal]->user_data = this; + lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); + if (settingsController.GetStopWatchSleepMode() == Controllers::Settings::StopWatchSleepMode::Disable) { + lv_checkbox_set_checked(cbOption[optionsTotal], true); + } + + optionsTotal++; + cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text_static(cbOption[optionsTotal], " Enable"); + cbOption[optionsTotal]->user_data = this; + lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); + if (settingsController.GetStopWatchSleepMode() == Controllers::Settings::StopWatchSleepMode::Enable) { + lv_checkbox_set_checked(cbOption[optionsTotal], true); + } + optionsTotal++; +} + +SettingStopWatch::~SettingStopWatch() { + lv_obj_clean(lv_scr_act()); + settingsController.SaveSettings(); +} + +void SettingStopWatch::UpdateSelected(lv_obj_t* object, lv_event_t event) { + if (event == LV_EVENT_VALUE_CHANGED) { + for (int i = 0; i < optionsTotal; i++) { + if (object == cbOption[i]) { + lv_checkbox_set_checked(cbOption[i], true); + + if (i == 0) { + settingsController.SetStopWatchSleepMode(Controllers::Settings::StopWatchSleepMode::Disable); + }; + if (i == 1) { + settingsController.SetStopWatchSleepMode(Controllers::Settings::StopWatchSleepMode::Enable); + }; + + } else { + lv_checkbox_set_checked(cbOption[i], false); + } + } + } +} \ No newline at end of file diff --git a/src/displayapp/screens/settings/SettingStopWatch.h b/src/displayapp/screens/settings/SettingStopWatch.h new file mode 100644 index 0000000000..7fda80f2fb --- /dev/null +++ b/src/displayapp/screens/settings/SettingStopWatch.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include "components/settings/Settings.h" +#include "displayapp/screens/Screen.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingStopWatch : public Screen { + public: + SettingStopWatch(DisplayApp* app, Pinetime::Controllers::Settings& settingsController); + ~SettingStopWatch() override; + + void UpdateSelected(lv_obj_t* object, lv_event_t event); + + private: + Controllers::Settings& settingsController; + uint8_t optionsTotal; + lv_obj_t* cbOption[2]; + }; + } + } +} diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index 1daf311ed0..f3ea223ba4 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -49,9 +49,9 @@ std::unique_ptr Settings::CreateScreen2() { std::array applications {{ {Symbols::shoe, "Steps", Apps::SettingSteps}, + {Symbols::stopWatch, "Stopwatch", Apps::SettingStopWatch}, {Symbols::clock, "Set date", Apps::SettingSetDate}, {Symbols::clock, "Set time", Apps::SettingSetTime}, - {Symbols::batteryHalf, "Battery", Apps::BatteryInfo} }}; return std::make_unique(1, 3, app, settingsController, applications); @@ -60,10 +60,10 @@ std::unique_ptr Settings::CreateScreen2() { std::unique_ptr Settings::CreateScreen3() { std::array applications {{ + {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, {Symbols::paintbrush, "PTS Colors", Apps::SettingPineTimeStyle}, {Symbols::check, "Firmware", Apps::FirmwareValidation}, {Symbols::list, "About", Apps::SysInfo}, - {Symbols::none, "None", Apps::None}, }}; return std::make_unique(2, 3, app, settingsController, applications);