Skip to content

Commit 8d87a9e

Browse files
JustScottJF002
authored andcommitted
Improved the Terminal Watchfaces UI
+ Reorder code to match the widgets order in the UI. + Moved all objects (rows) into a container + 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](#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.
1 parent f88c69a commit 8d87a9e

File tree

3 files changed

+88
-70
lines changed

3 files changed

+88
-70
lines changed

src/displayapp/InfiniTimeTheme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Colors {
88
static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0);
99
static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff);
1010
static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0);
11+
static constexpr lv_color_t gray = LV_COLOR_MAKE(0x50, 0x50, 0x50);
1112

1213
static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e);
1314
static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38);
Lines changed: 81 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include <lvgl/lvgl.h>
22
#include "displayapp/screens/WatchFaceTerminal.h"
33
#include "displayapp/screens/BatteryIcon.h"
4-
#include "displayapp/screens/NotificationIcon.h"
5-
#include "displayapp/screens/Symbols.h"
64
#include "components/battery/BatteryController.h"
75
#include "components/ble/BleController.h"
86
#include "components/ble/NotificationManager.h"
@@ -11,6 +9,7 @@
119
#include "components/settings/Settings.h"
1210
#include "components/ble/SimpleWeatherService.h"
1311
#include "displayapp/screens/WeatherSymbols.h"
12+
#include "displayapp/InfiniTimeTheme.h"
1413

1514
using namespace Pinetime::Applications::Screens;
1615

@@ -31,44 +30,46 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController,
3130
heartRateController {heartRateController},
3231
motionController {motionController},
3332
weatherService {weatherService} {
34-
batteryValue = lv_label_create(lv_scr_act(), nullptr);
35-
lv_label_set_recolor(batteryValue, true);
36-
lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
37-
38-
connectState = lv_label_create(lv_scr_act(), nullptr);
39-
lv_label_set_recolor(connectState, true);
40-
lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);
4133

42-
notificationIcon = lv_label_create(lv_scr_act(), nullptr);
43-
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100);
34+
container = lv_cont_create(lv_scr_act(), nullptr);
35+
lv_cont_set_layout(container, LV_LAYOUT_COLUMN_LEFT);
36+
lv_cont_set_fit(container, LV_FIT_TIGHT);
37+
lv_obj_set_style_local_pad_inner(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, -3);
38+
lv_obj_set_style_local_bg_opa(container, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
4439

45-
label_date = lv_label_create(lv_scr_act(), nullptr);
46-
lv_label_set_recolor(label_date, true);
47-
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40);
40+
notificationIcon = lv_label_create(container, nullptr);
4841

49-
label_prompt_1 = lv_label_create(lv_scr_act(), nullptr);
50-
lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80);
42+
label_prompt_1 = lv_label_create(container, nullptr);
43+
lv_obj_set_style_local_text_color(label_prompt_1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
5144
lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now");
5245

53-
label_prompt_2 = lv_label_create(lv_scr_act(), nullptr);
54-
lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);
55-
lv_label_set_text_static(label_prompt_2, "user@watch:~ $");
56-
57-
label_time = lv_label_create(lv_scr_act(), nullptr);
46+
label_time = lv_label_create(container, nullptr);
5847
lv_label_set_recolor(label_time, true);
59-
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60);
6048

61-
heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
62-
lv_label_set_recolor(heartbeatValue, true);
63-
lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20);
49+
label_date = lv_label_create(container, nullptr);
50+
lv_label_set_recolor(label_date, true);
6451

65-
stepValue = lv_label_create(lv_scr_act(), nullptr);
52+
batteryValue = lv_label_create(container, nullptr);
53+
lv_label_set_recolor(batteryValue, true);
54+
55+
stepValue = lv_label_create(container, nullptr);
6656
lv_label_set_recolor(stepValue, true);
67-
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);
57+
lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange);
58+
59+
heartbeatValue = lv_label_create(container, nullptr);
60+
lv_label_set_recolor(heartbeatValue, true);
6861

69-
weather = lv_label_create(lv_scr_act(), nullptr);
62+
weather = lv_label_create(container, nullptr);
7063
lv_label_set_recolor(weather, true);
71-
lv_obj_align(weather, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40);
64+
65+
connectState = lv_label_create(container, nullptr);
66+
lv_label_set_recolor(connectState, true);
67+
68+
label_prompt_2 = lv_label_create(container, nullptr);
69+
lv_obj_set_style_local_text_color(label_prompt_2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
70+
lv_label_set_text_static(label_prompt_2, "user@watch:~ $");
71+
72+
lv_obj_align(container, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 7);
7273

7374
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
7475
Refresh();
@@ -80,33 +81,10 @@ WatchFaceTerminal::~WatchFaceTerminal() {
8081
}
8182

8283
void WatchFaceTerminal::Refresh() {
83-
powerPresent = batteryController.IsPowerPresent();
84-
batteryPercentRemaining = batteryController.PercentRemaining();
85-
if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) {
86-
lv_label_set_text_fmt(batteryValue, "[BATT]#387b54 %d%%", batteryPercentRemaining.Get());
87-
if (batteryController.IsPowerPresent()) {
88-
lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging");
89-
}
90-
}
91-
92-
bleState = bleController.IsConnected();
93-
bleRadioEnabled = bleController.IsRadioEnabled();
94-
if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
95-
if (!bleRadioEnabled.Get()) {
96-
lv_label_set_text_static(connectState, "[STAT]#0082fc Disabled#");
97-
} else {
98-
if (bleState.Get()) {
99-
lv_label_set_text_static(connectState, "[STAT]#0082fc Connected#");
100-
} else {
101-
lv_label_set_text_static(connectState, "[STAT]#0082fc Disconnected#");
102-
}
103-
}
104-
}
105-
10684
notificationState = notificationManager.AreNewNotificationsAvailable();
10785
if (notificationState.IsUpdated()) {
10886
if (notificationState.Get()) {
109-
lv_label_set_text_static(notificationIcon, "You have mail.");
87+
lv_label_set_text_static(notificationIcon, "[1]+ Notify");
11088
} else {
11189
lv_label_set_text_static(notificationIcon, "");
11290
}
@@ -128,35 +106,52 @@ void WatchFaceTerminal::Refresh() {
128106
hour = hour - 12;
129107
ampmChar[0] = 'P';
130108
}
131-
lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar);
109+
lv_label_set_text_fmt(label_time, "#ffffff [TIME]# #11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar);
132110
} else {
133-
lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d", hour, minute, second);
111+
lv_label_set_text_fmt(label_time, "#ffffff [TIME]# #11cc55 %02d:%02d:%02d#", hour, minute, second);
134112
}
135113

136114
currentDate = std::chrono::time_point_cast<std::chrono::days>(currentDateTime.Get());
137115
if (currentDate.IsUpdated()) {
138116
uint16_t year = dateTimeController.Year();
139117
Controllers::DateTime::Months month = dateTimeController.Month();
140118
uint8_t day = dateTimeController.Day();
141-
lv_label_set_text_fmt(label_date, "[DATE]#007fff %04d-%02d-%02d#", short(year), char(month), char(day));
119+
lv_label_set_text_fmt(label_date, "#ffffff [DATE]# #007fff %04d-%02d-%02d#", short(year), char(month), char(day));
142120
}
143121
}
144122

123+
powerPresent = batteryController.IsPowerPresent();
124+
batteryPercentRemaining = batteryController.PercentRemaining();
125+
if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) {
126+
// HSV color model has red at 0° and green at 120°.
127+
// We lock satuation and brightness at 100% and traverse the cilinder
128+
// between red and green, thus avoiding the darker RGB on medium battery
129+
// charges and giving us a much nicer color range.
130+
uint8_t hue = batteryPercentRemaining.Get() * 120 / 100;
131+
lv_obj_set_style_local_text_color(batteryValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hsv_to_rgb(hue, 100, 100));
132+
lv_label_set_text_fmt(batteryValue, "#ffffff [BATT]# %d%%", batteryPercentRemaining.Get());
133+
if (batteryController.IsCharging()) {
134+
lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging");
135+
}
136+
}
137+
138+
stepCount = motionController.NbSteps();
139+
if (stepCount.IsUpdated()) {
140+
lv_label_set_text_fmt(stepValue, "#ffffff [STEP]# %lu steps", stepCount.Get());
141+
}
142+
145143
heartbeat = heartRateController.HeartRate();
146144
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
147145
if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
148146
if (heartbeatRunning.Get()) {
149-
lv_label_set_text_fmt(heartbeatValue, "[L_HR]#ee3311 %d bpm#", heartbeat.Get());
147+
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::deepOrange);
148+
lv_label_set_text_fmt(heartbeatValue, "#ffffff [L_HR]# %d bpm", heartbeat.Get());
150149
} else {
151-
lv_label_set_text_static(heartbeatValue, "[L_HR]#ee3311 ---#");
150+
lv_label_set_text_static(heartbeatValue, "#ffffff [L_HR]# ---");
151+
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);
152152
}
153153
}
154154

155-
stepCount = motionController.NbSteps();
156-
if (stepCount.IsUpdated()) {
157-
lv_label_set_text_fmt(stepValue, "[STEP]#ee3377 %lu steps#", stepCount.Get());
158-
}
159-
160155
currentWeather = weatherService.Current();
161156
if (currentWeather.IsUpdated()) {
162157
auto optCurrentWeather = currentWeather.Get();
@@ -167,9 +162,30 @@ void WatchFaceTerminal::Refresh() {
167162
temp = optCurrentWeather->temperature.Fahrenheit();
168163
tempUnit = 'F';
169164
}
170-
lv_label_set_text_fmt(weather, "[WTHR]#ffdd00 %d°%c %s#", temp, tempUnit, Symbols::GetSimpleCondition(optCurrentWeather->iconId));
165+
lv_label_set_text_fmt(weather,
166+
"#ffffff [WTHR]# #ffdd00 %d°%c %s#",
167+
temp,
168+
tempUnit,
169+
Symbols::GetSimpleCondition(optCurrentWeather->iconId));
171170
} else {
172-
lv_label_set_text(weather, "[WTHR]#ffdd00 ---");
171+
lv_label_set_text(weather, "#ffffff [WTHR]# #ffdd00 ---");
172+
}
173+
}
174+
175+
bleState = bleController.IsConnected();
176+
bleRadioEnabled = bleController.IsRadioEnabled();
177+
if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
178+
if (!bleRadioEnabled.Get()) {
179+
lv_label_set_text_static(connectState, "#ffffff [STAT]# Disabled");
180+
lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);
181+
} else {
182+
if (bleState.Get()) {
183+
lv_label_set_text_static(connectState, "#ffffff [STAT]# Connected");
184+
lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue);
185+
} else {
186+
lv_label_set_text_static(connectState, "#ffffff [STAT]# Disconnected");
187+
lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);
188+
}
173189
}
174190
}
175191
}

src/displayapp/screens/WatchFaceTerminal.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,17 @@ namespace Pinetime {
5050
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;
5151
Utility::DirtyValue<std::optional<Controllers::SimpleWeatherService::CurrentWeather>> currentWeather {};
5252

53+
lv_obj_t* container;
54+
lv_obj_t* notificationIcon;
55+
lv_obj_t* label_prompt_1;
5356
lv_obj_t* label_time;
5457
lv_obj_t* label_date;
55-
lv_obj_t* label_prompt_1;
56-
lv_obj_t* label_prompt_2;
5758
lv_obj_t* batteryValue;
58-
lv_obj_t* heartbeatValue;
5959
lv_obj_t* stepValue;
60-
lv_obj_t* notificationIcon;
61-
lv_obj_t* connectState;
60+
lv_obj_t* heartbeatValue;
6261
lv_obj_t* weather;
62+
lv_obj_t* connectState;
63+
lv_obj_t* label_prompt_2;
6364

6465
Controllers::DateTime& dateTimeController;
6566
const Controllers::Battery& batteryController;

0 commit comments

Comments
 (0)