Improved the Terminal Watchfaces UI

+ Reorder code to match the widgets order in the UI.

+ Use InfintimeTheme Colors instead of hardcoded hex values

+ Added a new InfinitimeTheme color: gray, using it to turn certain
  values gray when they contain no data

+ Implement @vkareh's [variable battery icon](https://github.com/InfiniTimeOrg/InfiniTime/pull/1964)
  color to the battery percentage text.

+ Replaced the 'You have mail.' notification message with the message
  '[1]+ Notify' to better fit the terminal lore.
This commit is contained in:
JustScott 2024-10-03 15:51:00 -05:00
parent a2356f2f4a
commit d2382e182e
3 changed files with 76 additions and 59 deletions

View file

@ -8,6 +8,7 @@ namespace Colors {
static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0); static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0);
static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff); static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff);
static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0); static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0);
static constexpr lv_color_t gray = LV_COLOR_MAKE(0x50, 0x50, 0x50);
static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e); static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e);
static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38); static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38);

View file

@ -2,13 +2,13 @@
#include "displayapp/screens/WatchFaceTerminal.h" #include "displayapp/screens/WatchFaceTerminal.h"
#include "displayapp/screens/BatteryIcon.h" #include "displayapp/screens/BatteryIcon.h"
#include "displayapp/screens/NotificationIcon.h" #include "displayapp/screens/NotificationIcon.h"
#include "displayapp/screens/Symbols.h"
#include "components/battery/BatteryController.h" #include "components/battery/BatteryController.h"
#include "components/ble/BleController.h" #include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h" #include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h" #include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h" #include "components/motion/MotionController.h"
#include "components/settings/Settings.h" #include "components/settings/Settings.h"
#include "displayapp/InfiniTimeTheme.h"
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
@ -27,40 +27,44 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController,
settingsController {settingsController}, settingsController {settingsController},
heartRateController {heartRateController}, heartRateController {heartRateController},
motionController {motionController} { motionController {motionController} {
batteryValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(batteryValue, true);
lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
connectState = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(connectState, true);
lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40);
notificationIcon = lv_label_create(lv_scr_act(), nullptr); notificationIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -90);
label_date = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_date, true);
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40);
label_prompt_1 = lv_label_create(lv_scr_act(), nullptr); label_prompt_1 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80); lv_obj_set_style_local_text_color(label_prompt_1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -70);
lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now"); lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now");
label_prompt_2 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);
lv_label_set_text_static(label_prompt_2, "user@watch:~ $");
label_time = lv_label_create(lv_scr_act(), nullptr); label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_time, true); lv_label_set_recolor(label_time, true);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -50);
heartbeatValue = lv_label_create(lv_scr_act(), nullptr); label_date = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(heartbeatValue, true); lv_label_set_recolor(label_date, true);
lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20); lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -30);
batteryValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(batteryValue, true);
lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -10);
stepValue = lv_label_create(lv_scr_act(), nullptr); stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(stepValue, true); lv_label_set_recolor(stepValue, true);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 10);
heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(heartbeatValue, true);
lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 30);
connectState = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(connectState, true);
lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 50);
label_prompt_2 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(label_prompt_2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 70);
lv_label_set_text_static(label_prompt_2, "user@watch:~ $");
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);
Refresh(); Refresh();
@ -72,33 +76,10 @@ WatchFaceTerminal::~WatchFaceTerminal() {
} }
void WatchFaceTerminal::Refresh() { void WatchFaceTerminal::Refresh() {
powerPresent = batteryController.IsPowerPresent();
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) {
lv_label_set_text_fmt(batteryValue, "[BATT]#387b54 %d%%", batteryPercentRemaining.Get());
if (batteryController.IsPowerPresent()) {
lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging");
}
}
bleState = bleController.IsConnected();
bleRadioEnabled = bleController.IsRadioEnabled();
if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
if (!bleRadioEnabled.Get()) {
lv_label_set_text_static(connectState, "[STAT]#0082fc Disabled#");
} else {
if (bleState.Get()) {
lv_label_set_text_static(connectState, "[STAT]#0082fc Connected#");
} else {
lv_label_set_text_static(connectState, "[STAT]#0082fc Disconnected#");
}
}
}
notificationState = notificationManager.AreNewNotificationsAvailable(); notificationState = notificationManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) { if (notificationState.IsUpdated()) {
if (notificationState.Get()) { if (notificationState.Get()) {
lv_label_set_text_static(notificationIcon, "You have mail."); lv_label_set_text_static(notificationIcon, "[1]+ Notify");
} else { } else {
lv_label_set_text_static(notificationIcon, ""); lv_label_set_text_static(notificationIcon, "");
} }
@ -120,9 +101,9 @@ void WatchFaceTerminal::Refresh() {
hour = hour - 12; hour = hour - 12;
ampmChar[0] = 'P'; ampmChar[0] = 'P';
} }
lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar); lv_label_set_text_fmt(label_time, "#fffff [TIME]# #11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar);
} else { } else {
lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d", hour, minute, second); lv_label_set_text_fmt(label_time, "#ffffff [TIME]# #11cc55 %02d:%02d:%02d#", hour, minute, second);
} }
currentDate = std::chrono::time_point_cast<std::chrono::days>(currentDateTime.Get()); currentDate = std::chrono::time_point_cast<std::chrono::days>(currentDateTime.Get());
@ -130,22 +111,57 @@ void WatchFaceTerminal::Refresh() {
uint16_t year = dateTimeController.Year(); uint16_t year = dateTimeController.Year();
Controllers::DateTime::Months month = dateTimeController.Month(); Controllers::DateTime::Months month = dateTimeController.Month();
uint8_t day = dateTimeController.Day(); uint8_t day = dateTimeController.Day();
lv_label_set_text_fmt(label_date, "[DATE]#007fff %04d-%02d-%02d#", short(year), char(month), char(day)); lv_label_set_text_fmt(label_date, "#ffffff [DATE]# #007fff %04d-%02d-%02d#", short(year), char(month), char(day));
} }
} }
powerPresent = batteryController.IsPowerPresent();
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) {
// HSV color model has red at 0° and green at 120°.
// We lock satuation and brightness at 100% and traverse the cilinder
// between red and green, thus avoiding the darker RGB on medium battery
// charges and giving us a much nicer color range.
uint8_t hue = batteryPercentRemaining.Get() * 120 / 100;
lv_obj_set_style_local_text_color(batteryValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hsv_to_rgb(hue, 100, 100));
lv_label_set_text_fmt(batteryValue, "#ffffff [BATT]# %d%%", batteryPercentRemaining.Get());
if (batteryController.IsCharging()) {
lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging");
}
}
stepCount = motionController.NbSteps();
if (stepCount.IsUpdated()) {
lv_label_set_text_fmt(stepValue, "#ffffff [STEP]# %lu steps", stepCount.Get());
}
heartbeat = heartRateController.HeartRate(); heartbeat = heartRateController.HeartRate();
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
if (heartbeatRunning.Get()) { if (heartbeatRunning.Get()) {
lv_label_set_text_fmt(heartbeatValue, "[L_HR]#ee3311 %d bpm#", heartbeat.Get());
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::deepOrange);
lv_label_set_text_fmt(heartbeatValue, "#ffffff [L_HR]# %d bpm", heartbeat.Get());
} else { } else {
lv_label_set_text_static(heartbeatValue, "[L_HR]#ee3311 ---#"); lv_label_set_text_static(heartbeatValue, "#ffffff [L_HR]# ---");
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);
} }
} }
stepCount = motionController.NbSteps(); bleState = bleController.IsConnected();
if (stepCount.IsUpdated()) { bleRadioEnabled = bleController.IsRadioEnabled();
lv_label_set_text_fmt(stepValue, "[STEP]#ee3377 %lu steps#", stepCount.Get()); if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
if (!bleRadioEnabled.Get()) {
lv_label_set_text_static(connectState, "#ffffff [STAT]# Disabled");
lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);
} else {
if (bleState.Get()) {
lv_label_set_text_static(connectState, "#ffffff [STAT]# Connected");
lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue);
} else {
lv_label_set_text_static(connectState, "#ffffff [STAT]# Disconnected");
lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);
}
}
} }
} }

View file

@ -47,15 +47,15 @@ namespace Pinetime {
Utility::DirtyValue<bool> notificationState {}; Utility::DirtyValue<bool> notificationState {};
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate; Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;
lv_obj_t* notificationIcon;
lv_obj_t* label_prompt_1;
lv_obj_t* label_time; lv_obj_t* label_time;
lv_obj_t* label_date; lv_obj_t* label_date;
lv_obj_t* label_prompt_1;
lv_obj_t* label_prompt_2;
lv_obj_t* batteryValue; lv_obj_t* batteryValue;
lv_obj_t* heartbeatValue;
lv_obj_t* stepValue; lv_obj_t* stepValue;
lv_obj_t* notificationIcon; lv_obj_t* heartbeatValue;
lv_obj_t* connectState; lv_obj_t* connectState;
lv_obj_t* label_prompt_2;
Controllers::DateTime& dateTimeController; Controllers::DateTime& dateTimeController;
const Controllers::Battery& batteryController; const Controllers::Battery& batteryController;