Merge branch 'develop' into refresh_rework

This commit is contained in:
Riku Isokoski 2021-08-15 13:35:15 +03:00
commit 3cef05b745
19 changed files with 216 additions and 180 deletions

BIN
doc/ui/example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

16
doc/ui_guidelines.md Normal file
View file

@ -0,0 +1,16 @@
# UI design guidelines
- Align objects all the way to the edge or corner
- Buttons should generally be at least 50px high
- Buttons should generally be on the bottom edge
- Make interactable objects **big**
- Recommendations for inner padding, aka distance between buttons:
- When aligning 4 objects: 4px, e.g. Settings
- When aligning 3 objects: 6px, e.g. App list
- When aligning 2 objects: 10px, e.g. Quick settings
- When using a page indicator, leave 8px for it on the right side
- It is acceptable to leave 8px on the left side as well to center the content
- Top bar takes at least 20px + padding
- Top bar right icons move 8px to the left when using a page indicator
![example layouts](./ui/example.png)

View file

@ -3,7 +3,8 @@
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
#include "app_timer.h" #include "app_timer.h"
APP_TIMER_DEF(vibTimer); APP_TIMER_DEF(shortVibTimer);
APP_TIMER_DEF(longVibTimer);
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
@ -13,19 +14,39 @@ MotorController::MotorController(Controllers::Settings& settingsController) : se
void MotorController::Init() { void MotorController::Init() {
nrf_gpio_cfg_output(pinMotor); nrf_gpio_cfg_output(pinMotor);
nrf_gpio_pin_set(pinMotor); nrf_gpio_pin_set(pinMotor);
app_timer_create(&vibTimer, APP_TIMER_MODE_SINGLE_SHOT, vibrate); app_timer_init();
app_timer_create(&shortVibTimer, APP_TIMER_MODE_SINGLE_SHOT, StopMotor);
app_timer_create(&longVibTimer, APP_TIMER_MODE_REPEATED, Ring);
} }
void MotorController::SetDuration(uint8_t motorDuration) { void MotorController::Ring(void* p_context) {
auto* motorController = static_cast<MotorController*>(p_context);
motorController->RunForDuration(50);
}
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) void MotorController::RunForDuration(uint8_t motorDuration) {
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) {
return; return;
}
nrf_gpio_pin_clear(pinMotor); nrf_gpio_pin_clear(pinMotor);
/* Start timer for motorDuration miliseconds and timer triggers vibrate() when it finishes*/ app_timer_start(shortVibTimer, APP_TIMER_TICKS(motorDuration), nullptr);
app_timer_start(vibTimer, APP_TIMER_TICKS(motorDuration), NULL);
} }
void MotorController::vibrate(void* p_context) { void MotorController::StartRinging() {
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) {
return;
}
Ring(this);
app_timer_start(longVibTimer, APP_TIMER_TICKS(1000), this);
}
void MotorController::StopRinging() {
app_timer_stop(longVibTimer);
nrf_gpio_pin_set(pinMotor);
}
void MotorController::StopMotor(void* p_context) {
nrf_gpio_pin_set(pinMotor); nrf_gpio_pin_set(pinMotor);
} }

View file

@ -12,11 +12,14 @@ namespace Pinetime {
public: public:
MotorController(Controllers::Settings& settingsController); MotorController(Controllers::Settings& settingsController);
void Init(); void Init();
void SetDuration(uint8_t motorDuration); void RunForDuration(uint8_t motorDuration);
void StartRinging();
static void StopRinging();
private: private:
static void Ring(void* p_context);
Controllers::Settings& settingsController; Controllers::Settings& settingsController;
static void vibrate(void* p_context); static void StopMotor(void* p_context);
}; };
} }
} }

View file

@ -336,12 +336,12 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
case Apps::Notifications: case Apps::Notifications:
currentScreen = std::make_unique<Screens::Notifications>( currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask->nimble().alertService(), Screens::Notifications::Modes::Normal); this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp); ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break; break;
case Apps::NotificationsPreview: case Apps::NotificationsPreview:
currentScreen = std::make_unique<Screens::Notifications>( currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask->nimble().alertService(), Screens::Notifications::Modes::Preview); this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Preview);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp); ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break; break;
case Apps::Timer: case Apps::Timer:

View file

@ -38,8 +38,9 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app,
lv_label_set_text(labelIsValidated, "Please #00ff00 Validate# this version or\n#ff0000 Reset# to rollback to the previous version."); lv_label_set_text(labelIsValidated, "Please #00ff00 Validate# this version or\n#ff0000 Reset# to rollback to the previous version.");
buttonValidate = lv_btn_create(lv_scr_act(), nullptr); buttonValidate = lv_btn_create(lv_scr_act(), nullptr);
lv_obj_align(buttonValidate, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
buttonValidate->user_data = this; buttonValidate->user_data = this;
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_event_cb(buttonValidate, ButtonEventHandler);
lv_obj_set_style_local_bg_color(buttonValidate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x009900)); lv_obj_set_style_local_bg_color(buttonValidate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x009900));
@ -48,6 +49,7 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app,
buttonReset = lv_btn_create(lv_scr_act(), nullptr); buttonReset = lv_btn_create(lv_scr_act(), nullptr);
buttonReset->user_data = this; 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_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_hex(0x990000)); lv_obj_set_style_local_bg_color(buttonReset, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x990000));
lv_obj_set_event_cb(buttonReset, ButtonEventHandler); lv_obj_set_event_cb(buttonReset, ButtonEventHandler);

View file

@ -6,10 +6,10 @@ Label::Label(uint8_t screenID, uint8_t numScreens, Pinetime::Applications::Displ
: Screen(app), labelText {labelText} { : Screen(app), labelText {labelText} {
if (numScreens > 1) { if (numScreens > 1) {
pageIndicatorBasePoints[0].x = 240 - 1; pageIndicatorBasePoints[0].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[0].y = 6; pageIndicatorBasePoints[0].y = 0;
pageIndicatorBasePoints[1].x = 240 - 1; pageIndicatorBasePoints[1].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[1].y = 240 - 6; pageIndicatorBasePoints[1].y = LV_VER_RES;
pageIndicatorBase = lv_line_create(lv_scr_act(), NULL); 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_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
@ -17,13 +17,13 @@ Label::Label(uint8_t screenID, uint8_t numScreens, Pinetime::Applications::Displ
lv_obj_set_style_local_line_rounded(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true); lv_obj_set_style_local_line_rounded(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2); lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2);
uint16_t indicatorSize = 228 / numScreens; uint16_t indicatorSize = LV_VER_RES / numScreens;
uint16_t indicatorPos = indicatorSize * screenID; uint16_t indicatorPos = indicatorSize * screenID;
pageIndicatorPoints[0].x = 240 - 1; pageIndicatorPoints[0].x = LV_HOR_RES - 1;
pageIndicatorPoints[0].y = (6 + indicatorPos); pageIndicatorPoints[0].y = indicatorPos;
pageIndicatorPoints[1].x = 240 - 1; pageIndicatorPoints[1].x = LV_HOR_RES - 1;
pageIndicatorPoints[1].y = (6 + indicatorPos) + indicatorSize; pageIndicatorPoints[1].y = indicatorPos + indicatorSize;
pageIndicator = lv_line_create(lv_scr_act(), NULL); 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_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);

View file

@ -25,42 +25,38 @@ List::List(uint8_t screenID,
settingsController.SetSettingsMenu(screenID); settingsController.SetSettingsMenu(screenID);
if (numScreens > 1) { if (numScreens > 1) {
pageIndicatorBasePoints[0].x = 240 - 1; pageIndicatorBasePoints[0].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[0].y = 6; pageIndicatorBasePoints[0].y = 0;
pageIndicatorBasePoints[1].x = 240 - 1; pageIndicatorBasePoints[1].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[1].y = 240 - 6; pageIndicatorBasePoints[1].y = LV_VER_RES;
pageIndicatorBase = lv_line_create(lv_scr_act(), NULL); 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_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_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); lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2);
uint16_t indicatorSize = 228 / numScreens; const uint16_t indicatorSize = LV_VER_RES / numScreens;
uint16_t indicatorPos = indicatorSize * screenID; const uint16_t indicatorPos = indicatorSize * screenID;
pageIndicatorPoints[0].x = 240 - 1; pageIndicatorPoints[0].x = LV_HOR_RES - 1;
pageIndicatorPoints[0].y = 6 + indicatorPos; pageIndicatorPoints[0].y = indicatorPos;
pageIndicatorPoints[1].x = 240 - 1; pageIndicatorPoints[1].x = LV_HOR_RES - 1;
pageIndicatorPoints[1].y = 6 + indicatorPos + indicatorSize; pageIndicatorPoints[1].y = indicatorPos + indicatorSize;
pageIndicator = lv_line_create(lv_scr_act(), NULL); 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_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_GRAY); lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
lv_obj_set_style_local_line_rounded(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicator, pageIndicatorPoints, 2); lv_line_set_points(pageIndicator, pageIndicatorPoints, 2);
} }
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); 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_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, 4);
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_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_pos(container1, 0, 0); lv_obj_set_pos(container1, 0, 0);
lv_obj_set_width(container1, LV_HOR_RES - 15); lv_obj_set_width(container1, LV_HOR_RES - 8);
lv_obj_set_height(container1, LV_VER_RES); lv_obj_set_height(container1, LV_VER_RES);
lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT);
@ -73,11 +69,11 @@ List::List(uint8_t screenID,
itemApps[i] = lv_btn_create(container1, nullptr); itemApps[i] = lv_btn_create(container1, nullptr);
lv_obj_set_style_local_bg_opa(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20); lv_obj_set_style_local_bg_opa(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_style_local_radius(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_set_style_local_radius(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 57);
lv_obj_set_style_local_bg_color(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); lv_obj_set_style_local_bg_color(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_width(itemApps[i], LV_HOR_RES - 25); lv_obj_set_width(itemApps[i], LV_HOR_RES - 8);
lv_obj_set_height(itemApps[i], 52); lv_obj_set_height(itemApps[i], 57);
lv_obj_set_event_cb(itemApps[i], ButtonEventHandler); lv_obj_set_event_cb(itemApps[i], ButtonEventHandler);
lv_btn_set_layout(itemApps[i], LV_LAYOUT_ROW_MID); lv_btn_set_layout(itemApps[i], LV_LAYOUT_ROW_MID);
itemApps[i]->user_data = this; itemApps[i]->user_data = this;

View file

@ -86,9 +86,9 @@ void Metronome::Refresh() {
counter--; counter--;
if (counter == 0) { if (counter == 0) {
counter = bpb; counter = bpb;
motorController.SetDuration(90); motorController.RunForDuration(90);
} else { } else {
motorController.SetDuration(30); motorController.RunForDuration(30);
} }
} }
} }

View file

@ -50,60 +50,55 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) {
Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::MusicService& music) : Screen(app), musicService(music) { Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::MusicService& music) : Screen(app), musicService(music) {
lv_obj_t* label; lv_obj_t* label;
lv_style_init(&btn_style);
lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 20);
lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_style_set_bg_opa(&btn_style, LV_STATE_DEFAULT, LV_OPA_20);
btnVolDown = lv_btn_create(lv_scr_act(), nullptr); btnVolDown = lv_btn_create(lv_scr_act(), nullptr);
btnVolDown->user_data = this; btnVolDown->user_data = this;
lv_obj_set_event_cb(btnVolDown, event_handler); lv_obj_set_event_cb(btnVolDown, event_handler);
lv_obj_set_size(btnVolDown, 65, 75); lv_obj_set_size(btnVolDown, 76, 76);
lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 15, -10); lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_set_style_local_radius(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_add_style(btnVolDown, LV_STATE_DEFAULT, &btn_style);
lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
label = lv_label_create(btnVolDown, nullptr); label = lv_label_create(btnVolDown, nullptr);
lv_label_set_text(label, Symbols::volumDown); lv_label_set_text(label, Symbols::volumDown);
lv_obj_set_hidden(btnVolDown, !displayVolumeButtons); lv_obj_set_hidden(btnVolDown, true);
btnVolUp = lv_btn_create(lv_scr_act(), nullptr); btnVolUp = lv_btn_create(lv_scr_act(), nullptr);
btnVolUp->user_data = this; btnVolUp->user_data = this;
lv_obj_set_event_cb(btnVolUp, event_handler); lv_obj_set_event_cb(btnVolUp, event_handler);
lv_obj_set_size(btnVolUp, 65, 75); lv_obj_set_size(btnVolUp, 76, 76);
lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10); lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_set_style_local_radius(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_add_style(btnVolUp, LV_STATE_DEFAULT, &btn_style);
lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
label = lv_label_create(btnVolUp, nullptr); label = lv_label_create(btnVolUp, nullptr);
lv_label_set_text(label, Symbols::volumUp); lv_label_set_text(label, Symbols::volumUp);
lv_obj_set_hidden(btnVolUp, !displayVolumeButtons); lv_obj_set_hidden(btnVolUp, true);
btnPrev = lv_btn_create(lv_scr_act(), nullptr); btnPrev = lv_btn_create(lv_scr_act(), nullptr);
btnPrev->user_data = this; btnPrev->user_data = this;
lv_obj_set_event_cb(btnPrev, event_handler); lv_obj_set_event_cb(btnPrev, event_handler);
lv_obj_set_size(btnPrev, 65, 75); lv_obj_set_size(btnPrev, 76, 76);
lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 15, -10); lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_set_style_local_radius(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_add_style(btnPrev, LV_STATE_DEFAULT, &btn_style);
lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
label = lv_label_create(btnPrev, nullptr); label = lv_label_create(btnPrev, nullptr);
lv_label_set_text(label, Symbols::stepBackward); lv_label_set_text(label, Symbols::stepBackward);
btnNext = lv_btn_create(lv_scr_act(), nullptr); btnNext = lv_btn_create(lv_scr_act(), nullptr);
btnNext->user_data = this; btnNext->user_data = this;
lv_obj_set_event_cb(btnNext, event_handler); lv_obj_set_event_cb(btnNext, event_handler);
lv_obj_set_size(btnNext, 65, 75); lv_obj_set_size(btnNext, 76, 76);
lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10); lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_set_style_local_radius(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_add_style(btnNext, LV_STATE_DEFAULT, &btn_style);
lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
label = lv_label_create(btnNext, nullptr); label = lv_label_create(btnNext, nullptr);
lv_label_set_text(label, Symbols::stepForward); lv_label_set_text(label, Symbols::stepForward);
btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
btnPlayPause->user_data = this; btnPlayPause->user_data = this;
lv_obj_set_event_cb(btnPlayPause, event_handler); lv_obj_set_event_cb(btnPlayPause, event_handler);
lv_obj_set_size(btnPlayPause, 65, 75); lv_obj_set_size(btnPlayPause, 76, 76);
lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -10); lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
lv_obj_set_style_local_radius(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_add_style(btnPlayPause, LV_STATE_DEFAULT, &btn_style);
lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
txtPlayPause = lv_label_create(btnPlayPause, nullptr); txtPlayPause = lv_label_create(btnPlayPause, nullptr);
lv_label_set_text(txtPlayPause, Symbols::play); lv_label_set_text(txtPlayPause, Symbols::play);
@ -150,6 +145,7 @@ Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Mus
Music::~Music() { Music::~Music() {
lv_task_del(taskRefresh); lv_task_del(taskRefresh);
lv_style_reset(&btn_style);
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
} }
@ -273,21 +269,19 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) {
bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
switch (event) { switch (event) {
case TouchEvents::SwipeUp: { case TouchEvents::SwipeUp: {
displayVolumeButtons = true; lv_obj_set_hidden(btnVolDown, false);
lv_obj_set_hidden(btnVolDown, !displayVolumeButtons); lv_obj_set_hidden(btnVolUp, false);
lv_obj_set_hidden(btnVolUp, !displayVolumeButtons);
lv_obj_set_hidden(btnNext, displayVolumeButtons); lv_obj_set_hidden(btnNext, true);
lv_obj_set_hidden(btnPrev, displayVolumeButtons); lv_obj_set_hidden(btnPrev, true);
return true; return true;
} }
case TouchEvents::SwipeDown: { case TouchEvents::SwipeDown: {
displayVolumeButtons = false; lv_obj_set_hidden(btnNext, false);
lv_obj_set_hidden(btnNext, displayVolumeButtons); lv_obj_set_hidden(btnPrev, false);
lv_obj_set_hidden(btnPrev, displayVolumeButtons);
lv_obj_set_hidden(btnVolDown, !displayVolumeButtons); lv_obj_set_hidden(btnVolDown, true);
lv_obj_set_hidden(btnVolUp, !displayVolumeButtons); lv_obj_set_hidden(btnVolUp, true);
return true; return true;
} }
case TouchEvents::SwipeLeft: { case TouchEvents::SwipeLeft: {

View file

@ -57,10 +57,11 @@ namespace Pinetime {
lv_obj_t* imgDiscAnim; lv_obj_t* imgDiscAnim;
lv_obj_t* txtTrackDuration; lv_obj_t* txtTrackDuration;
lv_style_t btn_style;
/** For the spinning disc animation */ /** For the spinning disc animation */
bool frameB; bool frameB;
bool displayVolumeButtons = false;
Pinetime::Controllers::MusicService& musicService; Pinetime::Controllers::MusicService& musicService;
std::string artist; std::string artist;

View file

@ -11,6 +11,7 @@ extern lv_font_t jetbrains_mono_bold_20;
Notifications::Notifications(DisplayApp* app, Notifications::Notifications(DisplayApp* app,
Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::AlertNotificationService& alertNotificationService,
Pinetime::Controllers::MotorController& motorController,
Modes mode) Modes mode)
: Screen(app), notificationManager {notificationManager}, alertNotificationService {alertNotificationService}, mode {mode} { : Screen(app), notificationManager {notificationManager}, alertNotificationService {alertNotificationService}, mode {mode} {
notificationManager.ClearNewNotificationFlag(); notificationManager.ClearNewNotificationFlag();
@ -36,7 +37,10 @@ Notifications::Notifications(DisplayApp* app,
} }
if (mode == Modes::Preview) { if (mode == Modes::Preview) {
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
motorController.StartRinging();
} else {
motorController.RunForDuration(35);
timeoutLine = lv_line_create(lv_scr_act(), nullptr); timeoutLine = lv_line_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_line_width(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3); lv_obj_set_style_local_line_width(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
@ -47,17 +51,20 @@ Notifications::Notifications(DisplayApp* app,
timeoutTickCountStart = xTaskGetTickCount(); timeoutTickCountStart = xTaskGetTickCount();
timeoutTickCountEnd = timeoutTickCountStart + (5 * 1024); timeoutTickCountEnd = timeoutTickCountStart + (5 * 1024);
} }
}
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
} }
Notifications::~Notifications() { Notifications::~Notifications() {
lv_task_del(taskRefresh); lv_task_del(taskRefresh);
// make sure we stop any vibrations before exiting
Controllers::MotorController::StopRinging();
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
} }
void Notifications::Refresh() { void Notifications::Refresh() {
if (mode == Modes::Preview) { if (mode == Modes::Preview && timeoutLine != nullptr) {
auto tick = xTaskGetTickCount(); auto tick = xTaskGetTickCount();
int32_t pos = 240 - ((tick - timeoutTickCountStart) / ((timeoutTickCountEnd - timeoutTickCountStart) / 240)); int32_t pos = 240 - ((tick - timeoutTickCountStart) / ((timeoutTickCountEnd - timeoutTickCountStart) / 240));
if (pos < 0) if (pos < 0)
@ -66,11 +73,13 @@ void Notifications::Refresh() {
timeoutLinePoints[1].x = pos; timeoutLinePoints[1].x = pos;
lv_line_set_points(timeoutLine, timeoutLinePoints, 2); lv_line_set_points(timeoutLine, timeoutLinePoints, 2);
} }
running = currentItem->IsRunning();
} }
bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) { bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
if (mode != Modes::Normal) if (mode != Modes::Normal) {
return true; return false;
}
switch (event) { switch (event) {
case Pinetime::Applications::TouchEvents::SwipeDown: { case Pinetime::Applications::TouchEvents::SwipeDown: {
@ -131,19 +140,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
} }
namespace { namespace {
static void AcceptIncomingCallEventHandler(lv_obj_t* obj, lv_event_t event) { void CallEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data); auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data);
item->OnAcceptIncomingCall(event); item->OnCallButtonEvent(obj, event);
}
static void MuteIncomingCallEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data);
item->OnMuteIncomingCall(event);
}
static void RejectIncomingCallEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data);
item->OnRejectIncomingCall(event);
} }
} }
@ -155,7 +154,6 @@ Notifications::NotificationItem::NotificationItem(const char* title,
Modes mode, Modes mode,
Pinetime::Controllers::AlertNotificationService& alertNotificationService) Pinetime::Controllers::AlertNotificationService& alertNotificationService)
: notifNr {notifNr}, notifNb {notifNb}, mode {mode}, alertNotificationService {alertNotificationService} { : notifNr {notifNr}, notifNb {notifNb}, mode {mode}, alertNotificationService {alertNotificationService} {
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), NULL); 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_hex(0x222222)); lv_obj_set_style_local_bg_color(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222));
@ -213,7 +211,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
bt_accept = lv_btn_create(lv_scr_act(), nullptr); bt_accept = lv_btn_create(lv_scr_act(), nullptr);
bt_accept->user_data = this; bt_accept->user_data = this;
lv_obj_set_event_cb(bt_accept, AcceptIncomingCallEventHandler); lv_obj_set_event_cb(bt_accept, CallEventHandler);
lv_obj_set_size(bt_accept, 76, 76); lv_obj_set_size(bt_accept, 76, 76);
lv_obj_align(bt_accept, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_align(bt_accept, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
label_accept = lv_label_create(bt_accept, nullptr); label_accept = lv_label_create(bt_accept, nullptr);
@ -222,7 +220,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
bt_reject = lv_btn_create(lv_scr_act(), nullptr); bt_reject = lv_btn_create(lv_scr_act(), nullptr);
bt_reject->user_data = this; bt_reject->user_data = this;
lv_obj_set_event_cb(bt_reject, RejectIncomingCallEventHandler); lv_obj_set_event_cb(bt_reject, CallEventHandler);
lv_obj_set_size(bt_reject, 76, 76); lv_obj_set_size(bt_reject, 76, 76);
lv_obj_align(bt_reject, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_align(bt_reject, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
label_reject = lv_label_create(bt_reject, nullptr); label_reject = lv_label_create(bt_reject, nullptr);
@ -231,7 +229,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
bt_mute = lv_btn_create(lv_scr_act(), nullptr); bt_mute = lv_btn_create(lv_scr_act(), nullptr);
bt_mute->user_data = this; bt_mute->user_data = this;
lv_obj_set_event_cb(bt_mute, MuteIncomingCallEventHandler); lv_obj_set_event_cb(bt_mute, CallEventHandler);
lv_obj_set_size(bt_mute, 76, 76); lv_obj_set_size(bt_mute, 76, 76);
lv_obj_align(bt_mute, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); lv_obj_align(bt_mute, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
label_mute = lv_label_create(bt_mute, nullptr); label_mute = lv_label_create(bt_mute, nullptr);
@ -247,25 +245,22 @@ Notifications::NotificationItem::NotificationItem(const char* title,
lv_label_set_text(backgroundLabel, ""); lv_label_set_text(backgroundLabel, "");
} }
void Notifications::NotificationItem::OnAcceptIncomingCall(lv_event_t event) { void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_t event) {
if (event != LV_EVENT_CLICKED) if (event != LV_EVENT_CLICKED) {
return; return;
}
Controllers::MotorController::StopRinging();
if (obj == bt_accept) {
alertNotificationService.AcceptIncomingCall(); alertNotificationService.AcceptIncomingCall();
} } else if (obj == bt_reject) {
void Notifications::NotificationItem::OnMuteIncomingCall(lv_event_t event) {
if (event != LV_EVENT_CLICKED)
return;
alertNotificationService.MuteIncomingCall();
}
void Notifications::NotificationItem::OnRejectIncomingCall(lv_event_t event) {
if (event != LV_EVENT_CLICKED)
return;
alertNotificationService.RejectIncomingCall(); alertNotificationService.RejectIncomingCall();
} else if (obj == bt_mute) {
alertNotificationService.MuteIncomingCall();
}
running = false;
} }
Notifications::NotificationItem::~NotificationItem() { Notifications::NotificationItem::~NotificationItem() {

View file

@ -5,6 +5,7 @@
#include <memory> #include <memory>
#include "Screen.h" #include "Screen.h"
#include "components/ble/NotificationManager.h" #include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h"
namespace Pinetime { namespace Pinetime {
namespace Controllers { namespace Controllers {
@ -19,6 +20,7 @@ namespace Pinetime {
explicit Notifications(DisplayApp* app, explicit Notifications(DisplayApp* app,
Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::AlertNotificationService& alertNotificationService,
Pinetime::Controllers::MotorController& motorController,
Modes mode); Modes mode);
~Notifications() override; ~Notifications() override;
@ -35,9 +37,10 @@ namespace Pinetime {
Modes mode, Modes mode,
Pinetime::Controllers::AlertNotificationService& alertNotificationService); Pinetime::Controllers::AlertNotificationService& alertNotificationService);
~NotificationItem(); ~NotificationItem();
void OnAcceptIncomingCall(lv_event_t event); bool IsRunning() const {
void OnMuteIncomingCall(lv_event_t event); return running;
void OnRejectIncomingCall(lv_event_t event); }
void OnCallButtonEvent(lv_obj_t*, lv_event_t event);
private: private:
uint8_t notifNr = 0; uint8_t notifNr = 0;
@ -57,6 +60,7 @@ namespace Pinetime {
lv_obj_t* bottomPlaceholder; lv_obj_t* bottomPlaceholder;
Modes mode; Modes mode;
Pinetime::Controllers::AlertNotificationService& alertNotificationService; Pinetime::Controllers::AlertNotificationService& alertNotificationService;
bool running = true;
}; };
private: private:
@ -72,7 +76,7 @@ namespace Pinetime {
bool validDisplay = false; bool validDisplay = false;
lv_point_t timeoutLinePoints[2] {{0, 1}, {239, 1}}; lv_point_t timeoutLinePoints[2] {{0, 1}, {239, 1}};
lv_obj_t* timeoutLine; lv_obj_t* timeoutLine = nullptr;
uint32_t timeoutTickCountStart; uint32_t timeoutTickCountStart;
uint32_t timeoutTickCountEnd; uint32_t timeoutTickCountEnd;

View file

@ -35,37 +35,35 @@ Tile::Tile(uint8_t screenID,
label_time = lv_label_create(lv_scr_act(), nullptr); label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_fmt(label_time, "%02i:%02i", dateTimeController.Hours(), dateTimeController.Minutes()); lv_label_set_text_fmt(label_time, "%02i:%02i", dateTimeController.Hours(), dateTimeController.Minutes());
lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER); lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label_time, nullptr, LV_ALIGN_IN_TOP_LEFT, 15, 6); lv_obj_align(label_time, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
// Battery // Battery
batteryIcon = lv_label_create(lv_scr_act(), nullptr); batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryController.PercentRemaining())); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryController.PercentRemaining()));
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -15, 6); lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -8, 0);
if (numScreens > 1) { if (numScreens > 1) {
pageIndicatorBasePoints[0].x = 240 - 1; pageIndicatorBasePoints[0].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[0].y = 6; pageIndicatorBasePoints[0].y = 0;
pageIndicatorBasePoints[1].x = 240 - 1; pageIndicatorBasePoints[1].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[1].y = 240 - 6; pageIndicatorBasePoints[1].y = LV_VER_RES;
pageIndicatorBase = lv_line_create(lv_scr_act(), nullptr); 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_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_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); lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2);
uint16_t indicatorSize = 228 / numScreens; const uint16_t indicatorSize = LV_VER_RES / numScreens;
uint16_t indicatorPos = indicatorSize * screenID; const uint16_t indicatorPos = indicatorSize * screenID;
pageIndicatorPoints[0].x = 240 - 1; pageIndicatorPoints[0].x = LV_HOR_RES - 1;
pageIndicatorPoints[0].y = 6 + indicatorPos; pageIndicatorPoints[0].y = indicatorPos;
pageIndicatorPoints[1].x = 240 - 1; pageIndicatorPoints[1].x = LV_HOR_RES - 1;
pageIndicatorPoints[1].y = 6 + indicatorPos + indicatorSize; pageIndicatorPoints[1].y = indicatorPos + indicatorSize;
pageIndicator = lv_line_create(lv_scr_act(), nullptr); 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_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_GRAY); lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
lv_obj_set_style_local_line_rounded(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicator, pageIndicatorPoints, 2); lv_line_set_points(pageIndicator, pageIndicatorPoints, 2);
} }
@ -85,7 +83,7 @@ Tile::Tile(uint8_t screenID,
btnm1 = lv_btnmatrix_create(lv_scr_act(), nullptr); btnm1 = lv_btnmatrix_create(lv_scr_act(), nullptr);
lv_btnmatrix_set_map(btnm1, btnmMap); lv_btnmatrix_set_map(btnm1, btnmMap);
lv_obj_set_size(btnm1, LV_HOR_RES - 10, LV_VER_RES - 60); lv_obj_set_size(btnm1, LV_HOR_RES - 16, LV_VER_RES - 60);
lv_obj_align(btnm1, NULL, LV_ALIGN_CENTER, 0, 10); lv_obj_align(btnm1, NULL, LV_ALIGN_CENTER, 0, 10);
lv_obj_set_style_local_radius(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, 20); lv_obj_set_style_local_radius(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, 20);
@ -93,6 +91,8 @@ Tile::Tile(uint8_t screenID,
lv_obj_set_style_local_bg_color(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, LV_COLOR_AQUA); 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_20); lv_obj_set_style_local_bg_opa(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DISABLED, LV_OPA_20);
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, lv_color_hex(0x111111));
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);
for (uint8_t i = 0; i < 6; i++) { for (uint8_t i = 0; i < 6; i++) {
if (applications[i].application == Apps::None) { if (applications[i].application == Apps::None) {

View file

@ -67,12 +67,12 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
batteryIcon = lv_label_create(lv_scr_act(), nullptr); batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryHalf); lv_label_set_text(batteryIcon, Symbols::batteryHalf);
lv_obj_align(batteryIcon, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -8, -4); lv_obj_align(batteryIcon, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
notificationIcon = lv_label_create(lv_scr_act(), NULL); 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_hex(0x00FF00));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 8, -4); lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
// Date - Day / Week day // Date - Day / Week day

View file

@ -35,7 +35,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
batteryIcon = lv_label_create(lv_scr_act(), nullptr); batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryFull); lv_label_set_text(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2); lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
batteryPlug = lv_label_create(lv_scr_act(), nullptr); 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_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
@ -50,7 +50,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
notificationIcon = lv_label_create(lv_scr_act(), nullptr); 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_hex(0x00FF00));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
label_date = lv_label_create(lv_scr_act(), nullptr); label_date = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60); lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60);
@ -75,7 +75,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); heartbeatIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(heartbeatIcon, Symbols::heartBeat); lv_label_set_text(heartbeatIcon, Symbols::heartBeat);
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
heartbeatValue = lv_label_create(lv_scr_act(), nullptr); heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
@ -85,7 +85,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
stepValue = lv_label_create(lv_scr_act(), nullptr); stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7)); lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
lv_label_set_text(stepValue, "0"); lv_label_set_text(stepValue, "0");
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
stepIcon = lv_label_create(lv_scr_act(), nullptr); stepIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7)); lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
@ -114,7 +114,7 @@ void WatchFaceDigital::Refresh() {
if (bleState.IsUpdated()) { if (bleState.IsUpdated()) {
lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get()));
} }
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5); lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
@ -212,7 +212,7 @@ void WatchFaceDigital::Refresh() {
lv_label_set_text_static(heartbeatValue, ""); lv_label_set_text_static(heartbeatValue, "");
} }
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2); lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
} }
@ -220,7 +220,7 @@ void WatchFaceDigital::Refresh() {
motionSensorOk = motionController.IsSensorOk(); motionSensorOk = motionController.IsSensorOk();
if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) { if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get()); lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get());
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
} }
} }

View file

@ -30,27 +30,35 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
motorController {motorController}, motorController {motorController},
settingsController {settingsController} { settingsController {settingsController} {
// This is the distance (padding) between all objects on this screen.
static constexpr uint8_t innerDistance = 10;
// Time // Time
label_time = lv_label_create(lv_scr_act(), nullptr); label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_fmt(label_time, "%02i:%02i", dateTimeController.Hours(), dateTimeController.Minutes()); lv_label_set_text_fmt(label_time, "%02i:%02i", dateTimeController.Hours(), dateTimeController.Minutes());
lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER); lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 15, 4); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0);
batteryIcon = lv_label_create(lv_scr_act(), nullptr); batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryController.PercentRemaining())); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryController.PercentRemaining()));
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -15, 4); lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
lv_obj_t* lbl_btn; 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
//static constexpr uint8_t buttonWidth = buttonHeight; // square buttons
static constexpr uint8_t buttonXOffset = (LV_HOR_RES_MAX - buttonWidth * 2 - innerDistance) / 2;
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_hex(0x111111));
btn1 = lv_btn_create(lv_scr_act(), nullptr); btn1 = lv_btn_create(lv_scr_act(), nullptr);
btn1->user_data = this; btn1->user_data = this;
lv_obj_set_event_cb(btn1, ButtonEventHandler); lv_obj_set_event_cb(btn1, ButtonEventHandler);
lv_obj_align(btn1, nullptr, LV_ALIGN_CENTER, -50, -30); lv_obj_add_style(btn1, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_style_local_radius(btn1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_set_size(btn1, buttonWidth, buttonHeight);
lv_obj_set_style_local_bg_color(btn1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); lv_obj_align(btn1, nullptr, LV_ALIGN_IN_TOP_LEFT, buttonXOffset, barHeight);
lv_obj_set_style_local_bg_grad_dir(btn1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn1, LV_FIT_TIGHT, LV_FIT_TIGHT);
btn1_lvl = lv_label_create(btn1, nullptr); btn1_lvl = lv_label_create(btn1, nullptr);
lv_obj_set_style_local_text_font(btn1_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); lv_obj_set_style_local_text_font(btn1_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
@ -59,12 +67,11 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn2 = lv_btn_create(lv_scr_act(), nullptr); btn2 = lv_btn_create(lv_scr_act(), nullptr);
btn2->user_data = this; btn2->user_data = this;
lv_obj_set_event_cb(btn2, ButtonEventHandler); lv_obj_set_event_cb(btn2, ButtonEventHandler);
lv_obj_align(btn2, nullptr, LV_ALIGN_CENTER, 50, -30); lv_obj_add_style(btn2, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_style_local_radius(btn2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_set_size(btn2, buttonWidth, buttonHeight);
lv_obj_set_style_local_bg_color(btn2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); lv_obj_align(btn2, nullptr, LV_ALIGN_IN_TOP_RIGHT, - buttonXOffset, barHeight);
lv_obj_set_style_local_bg_grad_dir(btn2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn2, LV_FIT_TIGHT, LV_FIT_TIGHT);
lv_obj_t* lbl_btn;
lbl_btn = lv_label_create(btn2, nullptr); 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_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::highlight);
@ -72,14 +79,11 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn3 = lv_btn_create(lv_scr_act(), nullptr); btn3 = lv_btn_create(lv_scr_act(), nullptr);
btn3->user_data = this; btn3->user_data = this;
lv_obj_set_event_cb(btn3, ButtonEventHandler); lv_obj_set_event_cb(btn3, ButtonEventHandler);
lv_obj_align(btn3, nullptr, LV_ALIGN_CENTER, -50, 60);
lv_btn_set_checkable(btn3, true); lv_btn_set_checkable(btn3, true);
lv_obj_set_style_local_radius(btn3, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); 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_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_bg_grad_dir(btn3, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_COLOR_GREEN); lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_COLOR_GREEN);
lv_obj_set_style_local_bg_grad_dir(btn1, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE); lv_obj_set_size(btn3, buttonWidth, buttonHeight);
lv_btn_set_fit2(btn3, LV_FIT_TIGHT, LV_FIT_TIGHT); lv_obj_align(btn3, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, buttonXOffset, 0);
btn3_lvl = lv_label_create(btn3, nullptr); 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); lv_obj_set_style_local_text_font(btn3_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
@ -94,11 +98,9 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn4 = lv_btn_create(lv_scr_act(), nullptr); btn4 = lv_btn_create(lv_scr_act(), nullptr);
btn4->user_data = this; btn4->user_data = this;
lv_obj_set_event_cb(btn4, ButtonEventHandler); lv_obj_set_event_cb(btn4, ButtonEventHandler);
lv_obj_align(btn4, nullptr, LV_ALIGN_CENTER, 50, 60); lv_obj_add_style(btn4, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_style_local_radius(btn4, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); lv_obj_set_size(btn4, buttonWidth, buttonHeight);
lv_obj_set_style_local_bg_color(btn4, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); lv_obj_align(btn4, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, - buttonXOffset, 0);
lv_obj_set_style_local_bg_grad_dir(btn4, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn4, LV_FIT_TIGHT, LV_FIT_TIGHT);
lbl_btn = lv_label_create(btn4, nullptr); lbl_btn = lv_label_create(btn4, nullptr);
lv_obj_set_style_local_text_font(lbl_btn, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); lv_obj_set_style_local_text_font(lbl_btn, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
@ -114,6 +116,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
} }
QuickSettings::~QuickSettings() { QuickSettings::~QuickSettings() {
lv_style_reset(&btn_style);
lv_task_del(taskUpdate); lv_task_del(taskUpdate);
lv_obj_clean(lv_scr_act()); lv_obj_clean(lv_scr_act());
settingsController.SaveSettings(); settingsController.SaveSettings();
@ -140,7 +143,7 @@ void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) {
if (lv_obj_get_state(btn3, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) { if (lv_obj_get_state(btn3, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) {
settingsController.SetVibrationStatus(Controllers::Settings::Vibration::ON); settingsController.SetVibrationStatus(Controllers::Settings::Vibration::ON);
motorController.SetDuration(35); motorController.RunForDuration(35);
lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn); lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn);
} else { } else {
settingsController.SetVibrationStatus(Controllers::Settings::Vibration::OFF); settingsController.SetVibrationStatus(Controllers::Settings::Vibration::OFF);

View file

@ -42,6 +42,8 @@ namespace Pinetime {
lv_obj_t* batteryIcon; lv_obj_t* batteryIcon;
lv_obj_t* label_time; lv_obj_t* label_time;
lv_style_t btn_style;
lv_obj_t* btn1; lv_obj_t* btn1;
lv_obj_t* btn1_lvl; lv_obj_t* btn1_lvl;
lv_obj_t* btn2; lv_obj_t* btn2;

View file

@ -266,14 +266,13 @@ void SystemTask::Work() {
if (isSleeping && !isWakingUp) { if (isSleeping && !isWakingUp) {
GoToRunning(); GoToRunning();
} }
motorController.SetDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
break; break;
case Messages::OnTimerDone: case Messages::OnTimerDone:
if (isSleeping && !isWakingUp) { if (isSleeping && !isWakingUp) {
GoToRunning(); GoToRunning();
} }
motorController.SetDuration(35); motorController.RunForDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
break; break;
case Messages::BleConnected: case Messages::BleConnected:
@ -326,7 +325,7 @@ void SystemTask::Work() {
stepCounterMustBeReset = true; stepCounterMustBeReset = true;
break; break;
case Messages::OnChargingEvent: case Messages::OnChargingEvent:
motorController.SetDuration(15); motorController.RunForDuration(15);
// Battery level is updated on every message - there's no need to do anything // Battery level is updated on every message - there's no need to do anything
break; break;