diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index ff43bb81..ad6bf77b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -579,7 +579,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(settingsController); break; case Apps::SettingWakeUp: - currentScreen = std::make_unique(settingsController); + currentScreen = std::make_unique(this, settingsController); break; case Apps::SettingDisplay: currentScreen = std::make_unique(settingsController); diff --git a/src/displayapp/screens/CheckboxList.cpp b/src/displayapp/screens/CheckboxList.cpp index 9eb80bba..f30dd503 100644 --- a/src/displayapp/screens/CheckboxList.cpp +++ b/src/displayapp/screens/CheckboxList.cpp @@ -17,9 +17,12 @@ CheckboxList::CheckboxList(const uint8_t screenID, const char* optionsSymbol, uint32_t originalValue, std::function OnValueChanged, - std::array options) + std::array options, + bool radioButton, + std::function IsChecked) : screenID {screenID}, OnValueChanged {std::move(OnValueChanged)}, + IsChecked_ {std::move(IsChecked)}, options {options}, value {originalValue}, pageIndicator(screenID, numScreens) { @@ -62,10 +65,16 @@ CheckboxList::CheckboxList(const uint8_t screenID, } cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); - SetRadioButtonStyle(cbOption[i]); + if (radioButton) { + SetRadioButtonStyle(cbOption[i]); + } - if (static_cast(originalValue - MaxItems * screenID) == i) { - lv_checkbox_set_checked(cbOption[i], true); + if (IsChecked_) { + lv_checkbox_set_checked(cbOption[i], IsChecked_(MaxItems * screenID + i)); + } else { + if (static_cast(originalValue - MaxItems * screenID) == i) { + lv_checkbox_set_checked(cbOption[i], true); + } } } } @@ -73,21 +82,43 @@ CheckboxList::CheckboxList(const uint8_t screenID, CheckboxList::~CheckboxList() { lv_obj_clean(lv_scr_act()); - OnValueChanged(value); + if (!IsChecked_) { + OnValueChanged(value); + } } void CheckboxList::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_VALUE_CHANGED) { - for (unsigned int i = 0; i < options.size(); i++) { - if (strcmp(options[i].name, "")) { - if (object == cbOption[i]) { - lv_checkbox_set_checked(cbOption[i], true); - value = MaxItems * screenID + i; - } else { - lv_checkbox_set_checked(cbOption[i], false); + if (!IsChecked_) { + for (unsigned int i = 0; i < options.size(); i++) { + if (strcmp(options[i].name, "")) { + if (object == cbOption[i]) { + lv_checkbox_set_checked(cbOption[i], true); + value = MaxItems * screenID + i; + } else { + lv_checkbox_set_checked(cbOption[i], false); + } + if (!options[i].enabled) { + lv_checkbox_set_disabled(cbOption[i]); + } } - if (!options[i].enabled) { - lv_checkbox_set_disabled(cbOption[i]); + } + } else { + for (unsigned int i = 0; i < options.size(); i++) { + if (strcmp(options[i].name, "")) { + if (object == cbOption[i]) { + OnValueChanged(MaxItems * screenID + i); + } + if (!options[i].enabled) { + lv_checkbox_set_disabled(cbOption[i]); + } + } + } + for (unsigned int i = 0; i < options.size(); i++) { + if (strcmp(options[i].name, "")) { + if (options[i].enabled) { + lv_checkbox_set_checked(cbOption[i], IsChecked_(MaxItems * screenID + i)); + } } } } diff --git a/src/displayapp/screens/CheckboxList.h b/src/displayapp/screens/CheckboxList.h index c6119970..bfbb03fe 100644 --- a/src/displayapp/screens/CheckboxList.h +++ b/src/displayapp/screens/CheckboxList.h @@ -27,13 +27,16 @@ namespace Pinetime { const char* optionsSymbol, uint32_t originalValue, std::function OnValueChanged, - std::array options); + std::array options, + bool radioButton = true, + std::function IsChecked = nullptr); ~CheckboxList() override; void UpdateSelected(lv_obj_t* object, lv_event_t event); private: const uint8_t screenID; std::function OnValueChanged; + std::function IsChecked_; std::array options; std::array cbOption; uint32_t value; diff --git a/src/displayapp/screens/settings/SettingWakeUp.cpp b/src/displayapp/screens/settings/SettingWakeUp.cpp index 4649dc82..6331d6e6 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.cpp +++ b/src/displayapp/screens/settings/SettingWakeUp.cpp @@ -1,57 +1,59 @@ #include "displayapp/screens/settings/SettingWakeUp.h" #include -#include "displayapp/DisplayApp.h" + #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" -#include "components/settings/Settings.h" +#include "displayapp/screens/CheckboxList.h" #include "displayapp/screens/Styles.h" using namespace Pinetime::Applications::Screens; -constexpr std::array SettingWakeUp::options; +constexpr const char* SettingWakeUp::title; +constexpr const char* SettingWakeUp::symbol; -namespace { - void event_handler(lv_obj_t* obj, lv_event_t event) { - auto* screen = static_cast(obj->user_data); - if (event == LV_EVENT_VALUE_CHANGED) { - screen->UpdateSelected(obj); +constexpr std::array SettingWakeUp::options; + +std::unique_ptr SettingWakeUp::CreateScreen(unsigned int screenNum) const { + std::array optionsOnThisScreen; + for (int i = 0; i < settingsPerScreen; i++) { + if (i + (screenNum * settingsPerScreen) >= options.size()) { + optionsOnThisScreen[i] = {"", false}; + } else { + auto& item = options[i + (screenNum * settingsPerScreen)]; + optionsOnThisScreen[i] = Screens::CheckboxList::Item {item.name, true}; } } + + return std::make_unique( + screenNum, + nScreens, + title, + symbol, + optionsCount, + [this, &settings = settingsController](uint32_t index) { + bool currentState = settingsController.isWakeUpModeOn(options[index].wakeUpMode); + settingsController.setWakeUpMode(options[index].wakeUpMode, !currentState); + }, + optionsOnThisScreen, + false, + [this, &settings = settingsController](uint32_t index) { + bool currentState = settingsController.isWakeUpModeOn(options[index].wakeUpMode); + return currentState; + }); } -SettingWakeUp::SettingWakeUp(Pinetime::Controllers::Settings& settingsController) : 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, 35); - lv_obj_set_width(container1, LV_HOR_RES - 20); - lv_obj_set_height(container1, LV_VER_RES - 20); - 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, "Wake Up"); - 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::eye); - lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); - lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - - 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.isWakeUpModeOn(static_cast(i))) { - lv_checkbox_set_checked(cbOption[i], true); - } - cbOption[i]->user_data = this; - lv_obj_set_event_cb(cbOption[i], event_handler); +auto SettingWakeUp::CreateScreenList() const { + std::array()>, nScreens> screens; + for (size_t i = 0; i < screens.size(); i++) { + screens[i] = [this, i]() -> std::unique_ptr { + return CreateScreen(i); + }; } + return screens; +} + +SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) + : settingsController {settingsController}, screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} { } SettingWakeUp::~SettingWakeUp() { @@ -59,21 +61,6 @@ SettingWakeUp::~SettingWakeUp() { settingsController.SaveSettings(); } -void SettingWakeUp::UpdateSelected(lv_obj_t* object) { - // Find the index of the checkbox that triggered the event - for (size_t i = 0; i < options.size(); i++) { - if (cbOption[i] == object) { - bool currentState = settingsController.isWakeUpModeOn(options[i].wakeUpMode); - settingsController.setWakeUpMode(options[i].wakeUpMode, !currentState); - break; - } - } - - // Update checkbox according to current wakeup modes. - // This is needed because we can have extra logic when setting or unsetting wakeup modes, - // for example, when setting SingleTap, DoubleTap is unset and vice versa. - auto modes = settingsController.getWakeUpModes(); - for (size_t i = 0; i < options.size(); ++i) { - lv_checkbox_set_checked(cbOption[i], modes[i]); - } +bool SettingWakeUp::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return screens.OnTouchEvent(event); } diff --git a/src/displayapp/screens/settings/SettingWakeUp.h b/src/displayapp/screens/settings/SettingWakeUp.h index 61edabce..176b0495 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.h +++ b/src/displayapp/screens/settings/SettingWakeUp.h @@ -3,8 +3,11 @@ #include #include #include -#include "components/settings/Settings.h" + #include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" +#include "displayapp/screens/Symbols.h" +#include "components/settings/Settings.h" namespace Pinetime { @@ -13,19 +16,26 @@ namespace Pinetime { class SettingWakeUp : public Screen { public: - SettingWakeUp(Pinetime::Controllers::Settings& settingsController); + SettingWakeUp(DisplayApp* app, Pinetime::Controllers::Settings& settingsController); ~SettingWakeUp() override; - void UpdateSelected(lv_obj_t* object); + bool OnTouchEvent(TouchEvents event) override; private: + auto CreateScreenList() const; + std::unique_ptr CreateScreen(unsigned int screenNum) const; + struct Option { Controllers::Settings::WakeUpMode wakeUpMode; const char* name; }; + static constexpr int settingsPerScreen = 4; + static constexpr int optionsCount = 5; + static constexpr int nScreens = (optionsCount - 1) / settingsPerScreen + 1; + Controllers::Settings& settingsController; - static constexpr std::array options = {{ + static constexpr std::array options = {{ {Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"}, {Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"}, {Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"}, @@ -33,7 +43,10 @@ namespace Pinetime { {Controllers::Settings::WakeUpMode::LowerWrist, "Lower Wrist"}, }}; - lv_obj_t* cbOption[options.size()]; + static constexpr const char* title = "Wake Up"; + static constexpr const char* symbol = Symbols::eye; + + ScreenList screens; }; } }