Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SettingWakeUp: use Checkboxlist.h #2123

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
currentScreen = std::make_unique<Screens::SettingWeatherFormat>(settingsController);
break;
case Apps::SettingWakeUp:
currentScreen = std::make_unique<Screens::SettingWakeUp>(settingsController);
currentScreen = std::make_unique<Screens::SettingWakeUp>(this, settingsController);
break;
case Apps::SettingDisplay:
currentScreen = std::make_unique<Screens::SettingDisplay>(this, settingsController);
Expand Down
59 changes: 45 additions & 14 deletions src/displayapp/screens/CheckboxList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ CheckboxList::CheckboxList(const uint8_t screenID,
const char* optionsSymbol,
uint32_t originalValue,
std::function<void(uint32_t)> OnValueChanged,
std::array<Item, MaxItems> options)
std::array<Item, MaxItems> options,
bool radioButton,
std::function<bool(uint32_t)> IsChecked)
: screenID {screenID},
OnValueChanged {std::move(OnValueChanged)},
IsChecked_ {std::move(IsChecked)},
options {options},
value {originalValue},
pageIndicator(screenID, numScreens) {
Expand Down Expand Up @@ -62,32 +65,60 @@ 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<unsigned int>(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<unsigned int>(originalValue - MaxItems * screenID) == i) {
lv_checkbox_set_checked(cbOption[i], true);
}
}
}
}
}

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]);
}
}
}
} 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]);
}
}
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));
}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/displayapp/screens/CheckboxList.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ namespace Pinetime {
const char* optionsSymbol,
uint32_t originalValue,
std::function<void(uint32_t)> OnValueChanged,
std::array<Item, MaxItems> options);
std::array<Item, MaxItems> options,
bool radioButton = true,
std::function<bool(uint32_t)> IsChecked = nullptr);
~CheckboxList() override;
void UpdateSelected(lv_obj_t* object, lv_event_t event);

private:
const uint8_t screenID;
std::function<void(uint32_t)> OnValueChanged;
std::function<bool(uint32_t)> IsChecked_;
std::array<Item, MaxItems> options;
std::array<lv_obj_t*, MaxItems> cbOption;
uint32_t value;
Expand Down
101 changes: 44 additions & 57 deletions src/displayapp/screens/settings/SettingWakeUp.cpp
Original file line number Diff line number Diff line change
@@ -1,79 +1,66 @@
#include "displayapp/screens/settings/SettingWakeUp.h"
#include <lvgl/lvgl.h>
#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::Option, 5> SettingWakeUp::options;
constexpr const char* SettingWakeUp::title;
constexpr const char* SettingWakeUp::symbol;

constexpr std::array<SettingWakeUp::Option, SettingWakeUp::optionsCount> SettingWakeUp::options;

namespace {
void event_handler(lv_obj_t* obj, lv_event_t event) {
auto* screen = static_cast<SettingWakeUp*>(obj->user_data);
if (event == LV_EVENT_VALUE_CHANGED) {
screen->UpdateSelected(obj);
std::unique_ptr<Screen> SettingWakeUp::CreateScreen(unsigned int screenNum) const {
std::array<Screens::CheckboxList::Item, settingsPerScreen> 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};
}
}
}

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);
return std::make_unique<Screens::CheckboxList>(
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;
});
}

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<Controllers::Settings::WakeUpMode>(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<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;
}

SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
: settingsController {settingsController}, screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} {
}

SettingWakeUp::~SettingWakeUp() {
lv_obj_clean(lv_scr_act());
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);
}
23 changes: 18 additions & 5 deletions src/displayapp/screens/settings/SettingWakeUp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
#include <array>
#include <cstdint>
#include <lvgl/lvgl.h>
#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 {

Expand All @@ -13,27 +16,37 @@ 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<Screen> 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<Option, 5> options = {{
static constexpr std::array<Option, optionsCount> options = {{
{Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"},
{Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"},
{Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"},
{Controllers::Settings::WakeUpMode::Shake, "Shake Wake"},
{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<nScreens> screens;
};
}
}
Expand Down
Loading