-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Watchface: Numerals #2047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Watchface: Numerals #2047
Changes from all commits
f6731c1
3915d3a
206c88c
e25ca95
3905b3b
e2e063c
2d47679
f9add36
2115213
8f52251
faa5333
fe4a2ae
3d763b1
591ad5e
238f6a2
09e3a80
cb5796e
8762961
f160714
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,7 @@ namespace Pinetime { | |
| Terminal, | ||
| Infineat, | ||
| CasioStyleG7710, | ||
| Numerals, | ||
| PrideFlag, | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| #include "displayapp/screens/WatchFaceNumerals.h" | ||
|
|
||
| #include <lvgl/lvgl.h> | ||
| #include <cstdio> | ||
| #include "displayapp/screens/Symbols.h" | ||
| #include "components/ble/NotificationManager.h" | ||
| #include "components/settings/Settings.h" | ||
|
|
||
| using namespace Pinetime::Applications::Screens; | ||
|
|
||
| WatchFaceNumerals::WatchFaceNumerals(Controllers::DateTime& dateTimeController, | ||
| Controllers::NotificationManager& notificationManager, | ||
| Controllers::Settings& settingsController, | ||
| Controllers::FS& filesystem) | ||
| : currentDateTime {{}}, | ||
| dateTimeController {dateTimeController}, | ||
| notificationManager {notificationManager}, | ||
| settingsController {settingsController} { | ||
|
|
||
| lfs_file f = {}; | ||
| if (filesystem.FileOpen(&f, "/fonts/rounded_large.bin", LFS_O_RDONLY) >= 0) { | ||
| filesystem.FileClose(&f); | ||
| font_large = lv_font_load("F:/fonts/rounded_large.bin"); | ||
| } | ||
|
|
||
| if (filesystem.FileOpen(&f, "/fonts/rounded_small.bin", LFS_O_RDONLY) >= 0) { | ||
| filesystem.FileClose(&f); | ||
| font_small = lv_font_load("F:/fonts/rounded_small.bin"); | ||
| } | ||
|
|
||
| notificationIcon = lv_obj_create(lv_scr_act(), nullptr); | ||
| lv_obj_set_style_local_bg_color(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); | ||
| lv_obj_set_style_local_radius(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); | ||
| lv_obj_set_size(notificationIcon, 16, 16); | ||
| lv_obj_align(notificationIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 4, -76); | ||
| lv_obj_set_hidden(notificationIcon, true); | ||
|
|
||
| labelTimeHour = lv_label_create(lv_scr_act(), nullptr); | ||
| lv_obj_set_style_local_text_font(labelTimeHour, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_large); | ||
| lv_obj_set_style_local_text_color(labelTimeHour, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); | ||
liamcharger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| lv_obj_align(labelTimeHour, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -160, -125); | ||
|
|
||
| labelTimeMinute = lv_label_create(lv_scr_act(), nullptr); | ||
| lv_obj_set_style_local_text_font(labelTimeMinute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_large); | ||
| lv_obj_set_style_local_text_color(labelTimeMinute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA); | ||
| lv_obj_align(labelTimeMinute, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -160, 0); | ||
|
|
||
| labelTimeAMPM1 = lv_label_create(lv_scr_act(), nullptr); | ||
liamcharger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| lv_label_set_text_static(labelTimeAMPM1, ""); | ||
| lv_obj_set_style_local_text_font(labelTimeAMPM1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_small); | ||
| lv_obj_set_style_local_text_color(labelTimeAMPM1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this colour is being used a couple of times I think it would be best if were a |
||
| lv_obj_align(labelTimeAMPM1, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 2, -34); | ||
| // We use two labels for more flexibility with alignment | ||
| labelTimeAMPM2 = lv_label_create(lv_scr_act(), nullptr); | ||
| lv_label_set_text_static(labelTimeAMPM2, "M"); | ||
| lv_obj_set_style_local_text_font(labelTimeAMPM2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_small); | ||
| lv_obj_set_style_local_text_color(labelTimeAMPM2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); | ||
| lv_obj_align(labelTimeAMPM2, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); | ||
|
|
||
| dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr); | ||
| lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||
| lv_label_set_text(dateDayOfWeek, "---"); | ||
| lv_obj_set_style_local_text_font(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_small); | ||
| lv_obj_align(dateDayOfWeek, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); | ||
|
|
||
| dateDay = lv_label_create(lv_scr_act(), nullptr); | ||
| lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); | ||
| lv_label_set_text(dateDay, "--"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is about to be set in |
||
| lv_obj_set_style_local_text_font(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_small); | ||
| lv_obj_align(dateDay, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 36); | ||
|
|
||
| taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); | ||
| Refresh(); | ||
| } | ||
|
|
||
| WatchFaceNumerals::~WatchFaceNumerals() { | ||
| lv_task_del(taskRefresh); | ||
|
|
||
| if (font_large != nullptr) { | ||
| lv_font_free(font_large); | ||
| } | ||
| if (font_small != nullptr) { | ||
| lv_font_free(font_small); | ||
| } | ||
|
|
||
| lv_obj_clean(lv_scr_act()); | ||
| } | ||
|
|
||
| void WatchFaceNumerals::Refresh() { | ||
| notificationState = notificationManager.AreNewNotificationsAvailable(); | ||
| if (notificationState.IsUpdated()) { | ||
| lv_obj_set_hidden(notificationIcon, !notificationState.Get()); | ||
| } | ||
|
|
||
| currentDateTime = dateTimeController.CurrentDateTime(); | ||
| if (currentDateTime.IsUpdated()) { | ||
| auto hour = dateTimeController.Hours(); | ||
| auto minute = dateTimeController.Minutes(); | ||
| auto year = dateTimeController.Year(); | ||
| auto month = dateTimeController.Month(); | ||
| auto dayOfWeek = dateTimeController.DayOfWeek(); | ||
| auto day = dateTimeController.Day(); | ||
|
|
||
| if (displayedHour != hour || displayedMinute != minute) { | ||
| displayedHour = hour; | ||
| displayedMinute = minute; | ||
|
|
||
| if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { | ||
| char ampmChar[2] = "A"; | ||
| if (hour == 0) { | ||
| hour = 12; | ||
| } else if (hour == 12) { | ||
| ampmChar[0] = 'P'; | ||
| } else if (hour > 12) { | ||
| hour = hour - 12; | ||
| ampmChar[0] = 'P'; | ||
| } | ||
| lv_label_set_text(labelTimeAMPM1, ampmChar); | ||
| lv_label_set_text_fmt(labelTimeHour, "%02d", hour); | ||
| lv_label_set_text_fmt(labelTimeMinute, "%02d", minute); | ||
| } else { | ||
| lv_obj_set_hidden(labelTimeAMPM2, true); | ||
| lv_label_set_text_fmt(labelTimeHour, "%02d", hour); | ||
| lv_label_set_text_fmt(labelTimeMinute, "%02d", minute); | ||
| } | ||
| } | ||
|
|
||
| if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { | ||
| lv_label_set_text_static(dateDayOfWeek, dateTimeController.DayOfWeekShortToString()); | ||
| lv_label_set_text_fmt(dateDay, "%d", day); | ||
| lv_obj_realign(dateDay); | ||
|
|
||
| currentYear = year; | ||
| currentMonth = month; | ||
| currentDayOfWeek = dayOfWeek; | ||
| currentDay = day; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| bool WatchFaceNumerals::IsAvailable(Pinetime::Controllers::FS& filesystem) { | ||
| lfs_file file = {}; | ||
|
|
||
| if (filesystem.FileOpen(&file, "/fonts/rounded_small.bin", LFS_O_RDONLY) < 0) { | ||
| return false; | ||
| } | ||
|
|
||
| filesystem.FileClose(&file); | ||
| if (filesystem.FileOpen(&file, "/fonts/rounded_large.bin", LFS_O_RDONLY) < 0) { | ||
| return false; | ||
| } | ||
|
|
||
| filesystem.FileClose(&file); | ||
| return true; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| #pragma once | ||
|
|
||
| #include <lvgl/lvgl.h> | ||
| #include <chrono> | ||
| #include <cstdint> | ||
| #include <memory> | ||
| #include <displayapp/Controllers.h> | ||
| #include "displayapp/screens/Screen.h" | ||
| #include "components/datetime/DateTimeController.h" | ||
| #include "utility/DirtyValue.h" | ||
| #include "displayapp/apps/Apps.h" | ||
|
|
||
| namespace Pinetime { | ||
| namespace Controllers { | ||
| class Settings; | ||
| class NotificationManager; | ||
| } | ||
|
|
||
| namespace Applications { | ||
| namespace Screens { | ||
|
|
||
| class WatchFaceNumerals : public Screen { | ||
| public: | ||
| WatchFaceNumerals(Controllers::DateTime& dateTimeController, | ||
| Controllers::NotificationManager& notificationManager, | ||
| Controllers::Settings& settingsController, | ||
| Controllers::FS& fs); | ||
| ~WatchFaceNumerals() override; | ||
|
|
||
| void Refresh() override; | ||
|
|
||
| static bool IsAvailable(Pinetime::Controllers::FS& filesystem); | ||
|
|
||
| private: | ||
| uint8_t displayedHour = -1; | ||
| uint8_t displayedMinute = -1; | ||
|
|
||
| uint16_t currentYear = 1970; | ||
| Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; | ||
| Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; | ||
| uint8_t currentDay = 0; | ||
| Utility::DirtyValue<bool> notificationState {}; | ||
| Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {}; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of storing all of the current day/hour/etc as variables, how about having two time points: Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>> currentDateTime;
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;Then if the currentDateTime is updated, redraw hours and minutes / AM/PM. Then set Make sure to remove the variables that are unused after this |
||
|
|
||
| lv_obj_t* labelTimeHour; | ||
| lv_obj_t* labelTimeMinute; | ||
| lv_obj_t* labelTimeAMPM1; | ||
| lv_obj_t* labelTimeAMPM2; | ||
| lv_obj_t* label_date; | ||
| lv_obj_t* notificationIcon; | ||
| lv_obj_t* dateDay; | ||
| lv_obj_t* dateDayOfWeek; | ||
|
|
||
| Controllers::DateTime& dateTimeController; | ||
| Controllers::NotificationManager& notificationManager; | ||
| Controllers::Settings& settingsController; | ||
|
|
||
| lv_font_t* font_large = nullptr; | ||
| lv_font_t* font_small = nullptr; | ||
|
|
||
| lv_task_t* taskRefresh; | ||
| }; | ||
| } | ||
|
|
||
| template <> | ||
| struct WatchFaceTraits<WatchFace::Numerals> { | ||
| static constexpr WatchFace watchFace = WatchFace::Numerals; | ||
| static constexpr const char* name = "Numerals"; | ||
|
|
||
| static Screens::Screen* Create(AppControllers& controllers) { | ||
| return new Screens::WatchFaceNumerals(controllers.dateTimeController, | ||
| controllers.notificationManager, | ||
| controllers.settingsController, | ||
| controllers.filesystem); | ||
| }; | ||
|
|
||
| static bool IsAvailable(Pinetime::Controllers::FS& filesystem) { | ||
| return Screens::WatchFaceNumerals::IsAvailable(filesystem); | ||
| } | ||
| }; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be
camelCase