Skip to content

Commit ea44d8f

Browse files
author
Aaron Züger
committed
add 24 hour clock watch face: SlowTime
1 parent e6b96c2 commit ea44d8f

File tree

7 files changed

+399
-3
lines changed

7 files changed

+399
-3
lines changed

src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ list(APPEND SOURCE_FILES
433433
displayapp/screens/WatchFaceTerminal.cpp
434434
displayapp/screens/WatchFacePineTimeStyle.cpp
435435
displayapp/screens/WatchFaceCasioStyleG7710.cpp
436+
displayapp/screens/WatchFaceSlowTime.cpp
436437

437438
##
438439

src/displayapp/WatchFaces.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ namespace Pinetime {
77
Analog = 1,
88
PineTimeStyle = 2,
99
Terminal = 3,
10-
Infineat = 4,
11-
CasioStyleG7710 = 5,
10+
SlowTime = 4,
11+
Infineat = 5,
12+
CasioStyleG7710 = 6,
1213
};
1314
}
1415
}

src/displayapp/screens/Clock.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "displayapp/screens/WatchFaceAnalog.h"
1414
#include "displayapp/screens/WatchFacePineTimeStyle.h"
1515
#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
16+
#include "displayapp/screens/WatchFaceSlowTime.h"
1617

1718
using namespace Pinetime::Applications::Screens;
1819
using namespace Pinetime::Applications;
@@ -55,6 +56,9 @@ Clock::Clock(Controllers::DateTime& dateTimeController,
5556
case WatchFace::CasioStyleG7710:
5657
return WatchFaceCasioStyleG7710();
5758
break;
59+
case WatchFace::SlowTime:
60+
return WatchFaceSlowTimeScreen();
61+
break;
5862
}
5963
return WatchFaceDigitalScreen();
6064
}()} {
@@ -131,3 +135,11 @@ std::unique_ptr<Screen> Clock::WatchFaceCasioStyleG7710() {
131135
motionController,
132136
filesystem);
133137
}
138+
139+
std::unique_ptr<Screen> Clock::WatchFaceSlowTimeScreen() {
140+
return std::make_unique<Screens::WatchFaceSlowTime>(dateTimeController,
141+
batteryController,
142+
bleController,
143+
notificationManager,
144+
settingsController);
145+
}

src/displayapp/screens/Clock.h

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ namespace Pinetime {
5454
std::unique_ptr<Screen> WatchFaceTerminalScreen();
5555
std::unique_ptr<Screen> WatchFaceInfineatScreen();
5656
std::unique_ptr<Screen> WatchFaceCasioStyleG7710();
57+
std::unique_ptr<Screen> WatchFaceSlowTimeScreen();
5758
};
5859
}
5960
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
#include "displayapp/screens/WatchFaceSlowTime.h"
2+
#include <cmath>
3+
#include <lvgl/lvgl.h>
4+
#include "displayapp/screens/BatteryIcon.h"
5+
#include "displayapp/screens/BleIcon.h"
6+
#include "displayapp/screens/Symbols.h"
7+
#include "displayapp/screens/NotificationIcon.h"
8+
#include "components/settings/Settings.h"
9+
#include "displayapp/InfiniTimeTheme.h"
10+
11+
using namespace Pinetime::Applications::Screens;
12+
13+
namespace {
14+
constexpr int16_t HourLength = 50;
15+
constexpr int16_t MinuteLength = 80;
16+
17+
// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
18+
const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
19+
20+
int16_t Cosine(int16_t angle) {
21+
return _lv_trigo_sin(angle + 90);
22+
}
23+
24+
int16_t Sine(int16_t angle) {
25+
return _lv_trigo_sin(angle);
26+
}
27+
28+
int16_t CoordinateXRelocate(int16_t x) {
29+
return (x + LV_HOR_RES / 2);
30+
}
31+
32+
int16_t CoordinateYRelocate(int16_t y) {
33+
return std::abs(y - LV_HOR_RES / 2);
34+
}
35+
36+
lv_point_t CoordinateRelocate(int16_t radius, int16_t angle) {
37+
return lv_point_t {.x = CoordinateXRelocate(radius * static_cast<int32_t>(Sine(angle)) / LV_TRIG_SCALE),
38+
.y = CoordinateYRelocate(radius * static_cast<int32_t>(Cosine(angle)) / LV_TRIG_SCALE)};
39+
}
40+
41+
}
42+
43+
WatchFaceSlowTime::WatchFaceSlowTime(Controllers::DateTime& dateTimeController,
44+
const Controllers::Battery& batteryController,
45+
const Controllers::Ble& bleController,
46+
Controllers::NotificationManager& notificationManager,
47+
Controllers::Settings& settingsController)
48+
: currentDateTime {{}},
49+
batteryIcon(true),
50+
dateTimeController {dateTimeController},
51+
batteryController {batteryController},
52+
bleController {bleController},
53+
notificationManager {notificationManager},
54+
settingsController {settingsController} {
55+
56+
sHour = 99;
57+
sMinute = 99;
58+
59+
minor_scales = lv_linemeter_create(lv_scr_act(), nullptr);
60+
lv_linemeter_set_scale(minor_scales, 360, 61);
61+
lv_linemeter_set_angle_offset(minor_scales, 180);
62+
lv_obj_set_size(minor_scales, 240, 240);
63+
lv_obj_align(minor_scales, nullptr, LV_ALIGN_CENTER, 0, 0);
64+
lv_obj_set_style_local_bg_opa(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
65+
lv_obj_set_style_local_scale_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4);
66+
lv_obj_set_style_local_scale_end_line_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1);
67+
lv_obj_set_style_local_scale_end_color(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
68+
69+
major_scales= lv_linemeter_create(lv_scr_act(), nullptr);
70+
lv_linemeter_set_scale(major_scales, 360, 13);
71+
lv_linemeter_set_angle_offset(major_scales, 30);
72+
lv_obj_set_size(major_scales, 240, 240);
73+
lv_obj_align(major_scales, nullptr, LV_ALIGN_CENTER, 0, 0);
74+
lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
75+
lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4);
76+
lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 2);
77+
lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
78+
79+
large_scales= lv_linemeter_create(lv_scr_act(), nullptr);
80+
lv_linemeter_set_scale(large_scales, 360, 13);
81+
lv_linemeter_set_angle_offset(large_scales, 15);
82+
lv_obj_set_size(large_scales, 220, 220);
83+
lv_obj_align(large_scales, nullptr, LV_ALIGN_CENTER, 0, 0);
84+
lv_obj_set_style_local_bg_opa(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
85+
lv_obj_set_style_local_scale_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 10);
86+
lv_obj_set_style_local_scale_end_line_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 3);
87+
lv_obj_set_style_local_scale_end_color(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
88+
89+
two = lv_label_create(lv_scr_act(), nullptr);
90+
lv_label_set_align(two, LV_LABEL_ALIGN_CENTER);
91+
lv_label_set_text_static(two, "2");
92+
lv_obj_set_pos(two, 160, 30);
93+
lv_obj_set_style_local_text_color(two, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
94+
95+
four = lv_label_create(lv_scr_act(), nullptr);
96+
lv_label_set_align(four, LV_LABEL_ALIGN_CENTER);
97+
lv_label_set_text_static(four, "4");
98+
lv_obj_set_pos(four, 192, 60);
99+
lv_obj_set_style_local_text_color(four, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
100+
101+
six = lv_label_create(lv_scr_act(), nullptr);
102+
lv_label_set_align(six, LV_LABEL_ALIGN_CENTER);
103+
lv_label_set_text_static(six, "6");
104+
lv_obj_set_pos(six, 206, 107);
105+
lv_obj_set_style_local_text_color(six, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
106+
107+
eight = lv_label_create(lv_scr_act(), nullptr);
108+
lv_label_set_align(eight, LV_LABEL_ALIGN_CENTER);
109+
lv_label_set_text_static(eight, "8");
110+
lv_obj_set_pos(eight, 192, 154);
111+
lv_obj_set_style_local_text_color(eight, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
112+
113+
ten = lv_label_create(lv_scr_act(), nullptr);
114+
lv_label_set_align(ten, LV_LABEL_ALIGN_CENTER);
115+
lv_label_set_text_static(ten, "10");
116+
lv_obj_set_pos(ten, 153, 184);
117+
lv_obj_set_style_local_text_color(ten, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
118+
119+
twelve = lv_label_create(lv_scr_act(), nullptr);
120+
lv_label_set_align(twelve, LV_LABEL_ALIGN_CENTER);
121+
lv_label_set_text_static(twelve, "12");
122+
lv_obj_set_pos(twelve, 107, 198);
123+
lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
124+
125+
fourteen = lv_label_create(lv_scr_act(), nullptr);
126+
lv_label_set_align(fourteen, LV_LABEL_ALIGN_CENTER);
127+
lv_label_set_text_static(fourteen, "14");
128+
lv_obj_set_pos(fourteen, 62, 184);
129+
lv_obj_set_style_local_text_color(fourteen, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
130+
131+
sixteen = lv_label_create(lv_scr_act(), nullptr);
132+
lv_label_set_align(sixteen, LV_LABEL_ALIGN_CENTER);
133+
lv_label_set_text_static(sixteen, "16");
134+
lv_obj_set_pos(sixteen, 32, 152);
135+
lv_obj_set_style_local_text_color(sixteen, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
136+
137+
eighteen = lv_label_create(lv_scr_act(), nullptr);
138+
lv_label_set_align(eighteen, LV_LABEL_ALIGN_CENTER);
139+
lv_label_set_text_static(eighteen, "18");
140+
lv_obj_set_pos(eighteen, 20, 107);
141+
lv_obj_set_style_local_text_color(eighteen, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
142+
143+
twenty = lv_label_create(lv_scr_act(), nullptr);
144+
lv_label_set_align(twenty, LV_LABEL_ALIGN_CENTER);
145+
lv_label_set_text_static(twenty, "20");
146+
lv_obj_set_pos(twenty, 32, 62);
147+
lv_obj_set_style_local_text_color(twenty, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
148+
149+
twentytwo = lv_label_create(lv_scr_act(), nullptr);
150+
lv_label_set_align(twentytwo, LV_LABEL_ALIGN_CENTER);
151+
lv_label_set_text_static(twentytwo, "22");
152+
lv_obj_set_pos(twentytwo, 62, 30);
153+
lv_obj_set_style_local_text_color(twentytwo, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
154+
155+
twentyfour = lv_label_create(lv_scr_act(), nullptr);
156+
lv_label_set_align(twentyfour, LV_LABEL_ALIGN_CENTER);
157+
lv_label_set_text_static(twentyfour, "24");
158+
lv_obj_set_pos(twentyfour, 107, 17);
159+
lv_obj_set_style_local_text_color(twentyfour, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
160+
161+
batteryIcon.Create(lv_scr_act());
162+
lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
163+
164+
plugIcon = lv_label_create(lv_scr_act(), nullptr);
165+
lv_label_set_text_static(plugIcon, Symbols::plug);
166+
lv_obj_align(plugIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
167+
168+
bleIcon = lv_label_create(lv_scr_act(), nullptr);
169+
lv_label_set_text_static(bleIcon, "");
170+
lv_obj_align(bleIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -30, 0);
171+
172+
notificationIcon = lv_label_create(lv_scr_act(), nullptr);
173+
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_LIME);
174+
lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false));
175+
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
176+
177+
// Date - Day / Week day
178+
179+
label_date_day = lv_label_create(lv_scr_act(), nullptr);
180+
lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAROON);
181+
lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day());
182+
lv_label_set_align(label_date_day, LV_LABEL_ALIGN_CENTER);
183+
lv_obj_align(label_date_day, nullptr, LV_ALIGN_CENTER, 50, 0);
184+
185+
minute_body = lv_line_create(lv_scr_act(), nullptr);
186+
hour_body = lv_line_create(lv_scr_act(), nullptr);
187+
188+
lv_style_init(&minute_line_style);
189+
lv_style_set_line_width(&minute_line_style, LV_STATE_DEFAULT, 3);
190+
lv_style_set_line_color(&minute_line_style, LV_STATE_DEFAULT, LV_COLOR_TEAL);
191+
lv_style_set_line_rounded(&minute_line_style, LV_STATE_DEFAULT, true);
192+
lv_obj_add_style(minute_body, LV_LINE_PART_MAIN, &minute_line_style);
193+
194+
lv_style_init(&hour_line_style);
195+
lv_style_set_line_width(&hour_line_style, LV_STATE_DEFAULT, 5);
196+
lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, LV_COLOR_TEAL);
197+
lv_style_set_line_rounded(&hour_line_style, LV_STATE_DEFAULT, true);
198+
lv_obj_add_style(hour_body, LV_LINE_PART_MAIN, &hour_line_style);
199+
200+
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
201+
202+
Refresh();
203+
}
204+
205+
WatchFaceSlowTime::~WatchFaceSlowTime() {
206+
lv_task_del(taskRefresh);
207+
208+
lv_style_reset(&hour_line_style);
209+
lv_style_reset(&minute_line_style);
210+
211+
lv_obj_clean(lv_scr_act());
212+
}
213+
214+
void WatchFaceSlowTime::UpdateClock() {
215+
uint8_t hour = dateTimeController.Hours();
216+
uint8_t minute = dateTimeController.Minutes();
217+
218+
if (sMinute != minute) {
219+
auto const angle = minute * 6;
220+
minute_point[0] = CoordinateRelocate(-15, angle);
221+
minute_point[1] = CoordinateRelocate(MinuteLength, angle);
222+
223+
lv_line_set_points(minute_body, minute_point, 2);
224+
}
225+
226+
if (sHour != hour || sMinute != minute) {
227+
sHour = hour;
228+
sMinute = minute;
229+
auto const angle = (hour * 15 + minute / 4);
230+
231+
hour_point[0] = CoordinateRelocate(-15, angle);
232+
hour_point[1] = CoordinateRelocate(HourLength, angle);
233+
234+
lv_line_set_points(hour_body, hour_point, 2);
235+
}
236+
}
237+
238+
void WatchFaceSlowTime::SetBatteryIcon() {
239+
auto batteryPercent = batteryPercentRemaining.Get();
240+
batteryIcon.SetBatteryPercentage(batteryPercent);
241+
}
242+
243+
void WatchFaceSlowTime::Refresh() {
244+
isCharging = batteryController.IsCharging();
245+
if (isCharging.IsUpdated()) {
246+
if (isCharging.Get()) {
247+
lv_obj_set_hidden(batteryIcon.GetObject(), true);
248+
lv_obj_set_hidden(plugIcon, false);
249+
} else {
250+
lv_obj_set_hidden(batteryIcon.GetObject(), false);
251+
lv_obj_set_hidden(plugIcon, true);
252+
SetBatteryIcon();
253+
}
254+
}
255+
if (!isCharging.Get()) {
256+
batteryPercentRemaining = batteryController.PercentRemaining();
257+
if (batteryPercentRemaining.IsUpdated()) {
258+
SetBatteryIcon();
259+
}
260+
}
261+
262+
bleState = bleController.IsConnected();
263+
if (bleState.IsUpdated()) {
264+
if (bleState.Get()) {
265+
lv_label_set_text_static(bleIcon, Symbols::bluetooth);
266+
} else {
267+
lv_label_set_text_static(bleIcon, "");
268+
}
269+
}
270+
271+
notificationState = notificationManager.AreNewNotificationsAvailable();
272+
273+
if (notificationState.IsUpdated()) {
274+
lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
275+
}
276+
277+
currentDateTime = dateTimeController.CurrentDateTime();
278+
if (currentDateTime.IsUpdated()) {
279+
UpdateClock();
280+
281+
currentDate = std::chrono::time_point_cast<days>(currentDateTime.Get());
282+
if (currentDate.IsUpdated()) {
283+
lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day());
284+
}
285+
}
286+
}

0 commit comments

Comments
 (0)