Skip to content
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
1 change: 1 addition & 0 deletions src/displayapp/InfiniTimeTheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Colors {
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 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 bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38);
Expand Down
10 changes: 10 additions & 0 deletions src/displayapp/screens/BatteryIcon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "displayapp/screens/Symbols.h"
#include "displayapp/icons/battery/batteryicon.c"
#include "displayapp/InfiniTimeTheme.h"
#include <lvgl/src/lv_misc/lv_color.h>

using namespace Pinetime::Applications::Screens;

Expand Down Expand Up @@ -51,3 +52,12 @@ const char* BatteryIcon::GetPlugIcon(bool isCharging) {
else
return "";
}

lv_color_t BatteryIcon::ColorFromPercentage(int batteryPercent) {
// HSV color model has red at 0° and green at 120°.
// We lock saturation and brightness at 100% and traverse the cylinder
// between red and green, thus avoiding the darker RGB on medium battery
// charges and giving us a much nicer color range.
const uint8_t hue = batteryPercent * 120 / 100;
return lv_color_hsv_to_rgb(hue, 100, 100);
}
1 change: 1 addition & 0 deletions src/displayapp/screens/BatteryIcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Pinetime {

static const char* GetUnknownIcon();
static const char* GetPlugIcon(bool isCharging);
static lv_color_t ColorFromPercentage(int batteryPercent);

private:
lv_obj_t* batteryImg;
Expand Down
128 changes: 70 additions & 58 deletions src/displayapp/screens/WatchFaceTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
#include "displayapp/screens/WatchFaceTerminal.h"
#include "displayapp/screens/BatteryIcon.h"
#include "displayapp/screens/NotificationIcon.h"
#include "displayapp/screens/Symbols.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
#include "displayapp/InfiniTimeTheme.h"

using namespace Pinetime::Applications::Screens;

Expand All @@ -27,40 +27,43 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController,
settingsController {settingsController},
heartRateController {heartRateController},
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);
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100);
container = lv_cont_create(lv_scr_act(), nullptr);
lv_cont_set_layout(container, LV_LAYOUT_COLUMN_LEFT);
lv_cont_set_fit(container, LV_FIT_TIGHT);
lv_obj_set_style_local_pad_inner(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, -3);
lv_obj_set_style_local_bg_opa(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);

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);
notificationIcon = lv_label_create(container, 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);
label_prompt_1 = lv_label_create(container, nullptr);
lv_obj_set_style_local_text_color(label_prompt_1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
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(container, nullptr);
lv_label_set_recolor(label_time, true);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60);

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, 20);
label_date = lv_label_create(container, nullptr);
lv_label_set_recolor(label_date, true);

stepValue = lv_label_create(lv_scr_act(), nullptr);
batteryValue = lv_label_create(container, nullptr);
lv_label_set_recolor(batteryValue, true);

stepValue = lv_label_create(container, nullptr);
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);

heartbeatValue = lv_label_create(container, nullptr);
lv_label_set_recolor(heartbeatValue, true);

connectState = lv_label_create(container, nullptr);
lv_label_set_recolor(connectState, true);

label_prompt_2 = lv_label_create(container, nullptr);
lv_obj_set_style_local_text_color(label_prompt_2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
lv_label_set_text_static(label_prompt_2, "user@watch:~ $");

lv_obj_align(container, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 20);

taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
Refresh();
Expand All @@ -72,33 +75,10 @@ WatchFaceTerminal::~WatchFaceTerminal() {
}

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();
if (notificationState.IsUpdated()) {
if (notificationState.Get()) {
lv_label_set_text_static(notificationIcon, "You have mail.");
lv_label_set_text_static(notificationIcon, "[1]+ Notify");
} else {
lv_label_set_text_static(notificationIcon, "");
}
Expand All @@ -120,32 +100,64 @@ void WatchFaceTerminal::Refresh() {
hour = hour - 12;
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 {
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());
if (currentDate.IsUpdated()) {
uint16_t year = dateTimeController.Year();
Controllers::DateTime::Months month = dateTimeController.Month();
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()) {
lv_obj_set_style_local_text_color(batteryValue,
LV_LABEL_PART_MAIN,
LV_STATE_DEFAULT,
BatteryIcon::ColorFromPercentage(batteryPercentRemaining.Get()));
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();
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
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 {
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();
if (stepCount.IsUpdated()) {
lv_label_set_text_fmt(stepValue, "[STEP]#ee3377 %lu steps#", stepCount.Get());
bleState = bleController.IsConnected();
bleRadioEnabled = bleController.IsRadioEnabled();
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);
}
}
}
}
9 changes: 5 additions & 4 deletions src/displayapp/screens/WatchFaceTerminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,16 @@ namespace Pinetime {
Utility::DirtyValue<bool> notificationState {};
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;

lv_obj_t* container;
lv_obj_t* notificationIcon;
lv_obj_t* label_prompt_1;
lv_obj_t* label_time;
lv_obj_t* label_date;
lv_obj_t* label_prompt_1;
lv_obj_t* label_prompt_2;
lv_obj_t* batteryValue;
lv_obj_t* heartbeatValue;
lv_obj_t* stepValue;
lv_obj_t* notificationIcon;
lv_obj_t* heartbeatValue;
lv_obj_t* connectState;
lv_obj_t* label_prompt_2;

Controllers::DateTime& dateTimeController;
const Controllers::Battery& batteryController;
Expand Down