Add PineTimeStyle watchface (#334)

* PineTimeStyle
* Move GPL license header
* Add step count gauge - replaces heartrate in sidebar
* Enable 12/24h functionality
* Set step gauge outer to be white when step goal is reached
* Add font source file
* Move static needle_colors array to member variable
* Add documentation on generating a font
* Replace .ttf with Google version, add link to font page

Co-authored-by: JF002 <JF002@users.noreply.github.com>
main
kieranc 2021-06-29 20:20:27 +07:00 committed by GitHub
parent 0045fb16b6
commit f317d54218
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1734 additions and 0 deletions

@ -235,6 +235,7 @@ set(LVGL_SRC
libs/lvgl/src/lv_widgets/lv_cont.h libs/lvgl/src/lv_widgets/lv_cont.h
libs/lvgl/src/lv_widgets/lv_cpicker.h libs/lvgl/src/lv_widgets/lv_cpicker.h
libs/lvgl/src/lv_widgets/lv_dropdown.h libs/lvgl/src/lv_widgets/lv_dropdown.h
libs/lvgl/src/lv_widgets/lv_gauge.h
libs/lvgl/src/lv_widgets/lv_img.h libs/lvgl/src/lv_widgets/lv_img.h
libs/lvgl/src/lv_widgets/lv_imgbtn.h libs/lvgl/src/lv_widgets/lv_imgbtn.h
libs/lvgl/src/lv_widgets/lv_keyboard.h libs/lvgl/src/lv_widgets/lv_keyboard.h
@ -321,6 +322,7 @@ set(LVGL_SRC
libs/lvgl/src/lv_widgets/lv_cont.c libs/lvgl/src/lv_widgets/lv_cont.c
libs/lvgl/src/lv_widgets/lv_cpicker.c libs/lvgl/src/lv_widgets/lv_cpicker.c
libs/lvgl/src/lv_widgets/lv_dropdown.c libs/lvgl/src/lv_widgets/lv_dropdown.c
libs/lvgl/src/lv_widgets/lv_gauge.c
libs/lvgl/src/lv_widgets/lv_img.c libs/lvgl/src/lv_widgets/lv_img.c
libs/lvgl/src/lv_widgets/lv_imgbtn.c libs/lvgl/src/lv_widgets/lv_imgbtn.c
libs/lvgl/src/lv_widgets/lv_keyboard.c libs/lvgl/src/lv_widgets/lv_keyboard.c
@ -423,6 +425,7 @@ list(APPEND SOURCE_FILES
displayapp/icons/bg_clock.c displayapp/icons/bg_clock.c
displayapp/screens/WatchFaceAnalog.cpp displayapp/screens/WatchFaceAnalog.cpp
displayapp/screens/WatchFaceDigital.cpp displayapp/screens/WatchFaceDigital.cpp
displayapp/screens/PineTimeStyle.cpp
## ##
@ -473,6 +476,7 @@ list(APPEND SOURCE_FILES
displayapp/fonts/jetbrains_mono_76.c displayapp/fonts/jetbrains_mono_76.c
displayapp/fonts/jetbrains_mono_42.c displayapp/fonts/jetbrains_mono_42.c
displayapp/fonts/lv_font_sys_48.c displayapp/fonts/lv_font_sys_48.c
displayapp/fonts/open_sans_light.c
displayapp/lv_pinetime_theme.c displayapp/lv_pinetime_theme.c
systemtask/SystemTask.cpp systemtask/SystemTask.cpp

@ -2,6 +2,7 @@
* [Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/) * [Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)
* [Awesome font from LVGL](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff) * [Awesome font from LVGL](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff)
* [Open Sans Light from Google](https://fonts.google.com/specimen/Open+Sans)
## Generate the fonts: ## Generate the fonts:
@ -14,6 +15,8 @@
* Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following * Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following
range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252` range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252`
* Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts` * Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts`
* Add the font .c file path to src/CMakeLists.txt
* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h
Add new symbols: Add new symbols:
@ -28,6 +31,21 @@ Add new symbols:
static constexpr const char* newSymbol = "\xEF\x86\x85"; static constexpr const char* newSymbol = "\xEF\x86\x85";
``` ```
## Simple method to generate a font
If you want to generate a basic font containing only numbers and letters, you can use the above settings but instead of specifying a range, simply list the characters you need in the Symbols field and leave the range blank. This is the approach used for the PineTimeStyle watchface.
This works well for fonts which will only be used to display numbers, but will fail if you try to add a colon or other punctuation.
* Open the [LVGL font converter](https://lvgl.io/tools/fontconverter)
* Name : open_sans_light
* Size : 150
* Bpp : 1 bit-per-pixel
* Do not enable font compression and horizontal subpixel hinting
* Load the file `open_sans_light.tff` (use the file in this repo to ensure the version matches) and specify the following symbols : `0123456789`
* Click on Convert, and download the file `open_sans_light.c` and copy it in `src/DisplayApp/Fonts`
* Add the font .c file path to src/CMakeLists.txt (search for jetbrains to find the appropriate location/format)
* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h (as above)
#### Navigation font #### Navigation font
To create the navigtion.ttf I use the web app [icomoon](https://icomoon.io/app) To create the navigtion.ttf I use the web app [icomoon](https://icomoon.io/app)

File diff suppressed because it is too large Load Diff

@ -14,6 +14,7 @@
#include "../DisplayApp.h" #include "../DisplayApp.h"
#include "WatchFaceDigital.h" #include "WatchFaceDigital.h"
#include "WatchFaceAnalog.h" #include "WatchFaceAnalog.h"
#include "PineTimeStyle.h"
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
@ -41,6 +42,9 @@ Clock::Clock(DisplayApp* app,
case 1: case 1:
return WatchFaceAnalogScreen(); return WatchFaceAnalogScreen();
break; break;
case 2:
return PineTimeStyleScreen();
break;
} }
return WatchFaceDigitalScreen(); return WatchFaceDigitalScreen();
}()} { }()} {
@ -76,6 +80,16 @@ std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {
app, dateTimeController, batteryController, bleController, notificatioManager, settingsController); app, dateTimeController, batteryController, bleController, notificatioManager, settingsController);
} }
std::unique_ptr<Screen> Clock::PineTimeStyleScreen() {
return std::make_unique<Screens::PineTimeStyle>(app,
dateTimeController,
batteryController,
bleController,
notificatioManager,
settingsController,
motionController);
}
/* /*
// Examples for more watch faces // Examples for more watch faces
std::unique_ptr<Screen> Clock::WatchFaceMinimalScreen() { std::unique_ptr<Screen> Clock::WatchFaceMinimalScreen() {

@ -50,6 +50,7 @@ namespace Pinetime {
std::unique_ptr<Screen> screen; std::unique_ptr<Screen> screen;
std::unique_ptr<Screen> WatchFaceDigitalScreen(); std::unique_ptr<Screen> WatchFaceDigitalScreen();
std::unique_ptr<Screen> WatchFaceAnalogScreen(); std::unique_ptr<Screen> WatchFaceAnalogScreen();
std::unique_ptr<Screen> PineTimeStyleScreen();
// Examples for more watch faces // Examples for more watch faces
// std::unique_ptr<Screen> WatchFaceMinimalScreen(); // std::unique_ptr<Screen> WatchFaceMinimalScreen();

@ -0,0 +1,340 @@
/*
* This file is part of the Infinitime distribution (https://github.com/JF002/Infinitime).
* Copyright (c) 2021 Kieran Cawthray.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* PineTimeStyle watchface for Infinitime created by Kieran Cawthray
* Based on WatchFaceDigital
* Style/layout copied from TimeStyle for Pebble by Dan Tilden (github.com/tilden)
*/
#include "PineTimeStyle.h"
#include <date/date.h>
#include <lvgl/lvgl.h>
#include <cstdio>
#include "BatteryIcon.h"
#include "BleIcon.h"
#include "NotificationIcon.h"
#include "Symbols.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
#include "../DisplayApp.h"
using namespace Pinetime::Applications::Screens;
PineTimeStyle::PineTimeStyle(DisplayApp* app,
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
Controllers::MotionController& motionController)
: Screen(app),
currentDateTime {{}},
dateTimeController {dateTimeController},
batteryController {batteryController},
bleController {bleController},
notificatioManager {notificatioManager},
settingsController {settingsController},
motionController {motionController} {
/* This sets the watchface number to return to after leaving the menu */
settingsController.SetClockFace(2);
displayedChar[0] = 0;
displayedChar[1] = 0;
displayedChar[2] = 0;
displayedChar[3] = 0;
displayedChar[4] = 0;
/* Create a 200px wide background rectangle */
timebar = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(timebar, 200, 240);
lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0);
/* Display the time */
timeDD1 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light);
lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
lv_label_set_text(timeDD1, "12");
lv_obj_align(timeDD1, timebar, LV_ALIGN_IN_TOP_MID, 5, 5);
timeDD2 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light);
lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
lv_label_set_text(timeDD2, "34");
lv_obj_align(timeDD2, timebar, LV_ALIGN_IN_BOTTOM_MID, 5, -5);
timeAMPM = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
lv_obj_set_style_local_text_line_space(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, -3);
lv_label_set_text(timeAMPM, "");
lv_obj_align(timeAMPM, timebar, LV_ALIGN_IN_BOTTOM_LEFT, 2, -20);
/* Create a 40px wide bar down the right side of the screen */
sidebar = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
lv_obj_set_style_local_radius(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(sidebar, 40, 240);
lv_obj_align(sidebar, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
/* Display icons */
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_label_set_text(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2);
batteryPlug = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_align(batteryPlug, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2);
bleIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25);
notificationIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40);
/* Calendar icon */
calendarOuter = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(calendarOuter, 34, 34);
lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0);
calendarInner = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xffffff));
lv_obj_set_style_local_radius(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(calendarInner, 27, 27);
lv_obj_align(calendarInner, calendarOuter, LV_ALIGN_CENTER, 0, 0);
calendarBar1 = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(calendarBar1, 3, 12);
lv_obj_align(calendarBar1, calendarOuter, LV_ALIGN_IN_TOP_MID, -6, -3);
calendarBar2 = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(calendarBar2, 3, 12);
lv_obj_align(calendarBar2, calendarOuter, LV_ALIGN_IN_TOP_MID, 6, -3);
calendarCrossBar1 = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(calendarCrossBar1, 8, 3);
lv_obj_align(calendarCrossBar1, calendarBar1, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
calendarCrossBar2 = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_size(calendarCrossBar2, 8, 3);
lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
/* Display date */
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_hex(0x000000));
lv_label_set_text(dateDayOfWeek, "THU");
lv_obj_align(dateDayOfWeek, sidebar, LV_ALIGN_CENTER, 0, -34);
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_hex(0x000000));
lv_label_set_text(dateDay, "25");
lv_obj_align(dateDay, sidebar, LV_ALIGN_CENTER, 0, 3);
dateMonth = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_label_set_text(dateMonth, "MAR");
lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32);
// Step count gauge
needle_colors[0] = LV_COLOR_WHITE;
stepGauge = lv_gauge_create(lv_scr_act(), nullptr);
lv_gauge_set_needle_count(stepGauge, 1, needle_colors);
lv_obj_set_size(stepGauge, 40, 40);
lv_obj_align(stepGauge, sidebar, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
lv_gauge_set_scale(stepGauge, 360, 11, 0);
lv_gauge_set_angle_offset(stepGauge, 180);
lv_gauge_set_critical_value(stepGauge, (settingsController.GetStepsGoal() / 100));
lv_gauge_set_range(stepGauge, 0, (settingsController.GetStepsGoal() / 100));
lv_gauge_set_value(stepGauge, 0, 0);
lv_obj_set_style_local_pad_right(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_pad_left(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_pad_bottom(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
lv_obj_set_style_local_scale_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4);
lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4);
lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, LV_OPA_COVER);
lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4);
lv_obj_set_style_local_pad_inner(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4);
backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_click(backgroundLabel, true);
lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP);
lv_obj_set_size(backgroundLabel, 240, 240);
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text(backgroundLabel, "");
}
PineTimeStyle::~PineTimeStyle() {
lv_obj_clean(lv_scr_act());
}
bool PineTimeStyle::Refresh() {
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get();
if (batteryController.IsCharging()) {
auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent();
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging));
lv_obj_realign(batteryPlug);
lv_label_set_text(batteryIcon, "");
} else {
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
lv_label_set_text(batteryPlug, "");
}
}
bleState = bleController.IsConnected();
if (bleState.IsUpdated()) {
if (bleState.Get() == true) {
lv_label_set_text(bleIcon, BleIcon::GetIcon(true));
lv_obj_realign(bleIcon);
} else {
lv_label_set_text(bleIcon, BleIcon::GetIcon(false));
}
}
notificationState = notificatioManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) {
if (notificationState.Get() == true) {
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true));
lv_obj_realign(notificationIcon);
} else {
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
}
}
currentDateTime = dateTimeController.CurrentDateTime();
if (currentDateTime.IsUpdated()) {
auto newDateTime = currentDateTime.Get();
auto dp = date::floor<date::days>(newDateTime);
auto time = date::make_time(newDateTime - dp);
auto yearMonthDay = date::year_month_day(dp);
auto year = (int) yearMonthDay.year();
auto month = static_cast<Pinetime::Controllers::DateTime::Months>((unsigned) yearMonthDay.month());
auto day = (unsigned) yearMonthDay.day();
auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding());
int hour = time.hours().count();
auto minute = time.minutes().count();
char minutesChar[3];
sprintf(minutesChar, "%02d", static_cast<int>(minute));
char hoursChar[3];
char ampmChar[5];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
sprintf(hoursChar, "%02d", hour);
} else {
if (hour == 0 && hour != 12) {
hour = 12;
sprintf(ampmChar, "A\nM");
} else if (hour == 12 && hour != 0) {
hour = 12;
sprintf(ampmChar, "P\nM");
} else if (hour < 12 && hour != 0) {
sprintf(ampmChar, "A\nM");
} else if (hour > 12 && hour != 0) {
hour = hour - 12;
sprintf(ampmChar, "P\nM");
}
sprintf(hoursChar, "%02d", hour);
}
if (hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] ||
minutesChar[1] != displayedChar[3]) {
displayedChar[0] = hoursChar[0];
displayedChar[1] = hoursChar[1];
displayedChar[2] = minutesChar[0];
displayedChar[3] = minutesChar[1];
char hourStr[3];
char minStr[3];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
lv_label_set_text(timeAMPM, ampmChar);
}
/* Display the time as 2 pairs of digits */
sprintf(hourStr, "%c%c", hoursChar[0], hoursChar[1]);
lv_label_set_text(timeDD1, hourStr);
sprintf(minStr, "%c%c", minutesChar[0], minutesChar[1]);
lv_label_set_text(timeDD2, minStr);
}
if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {
char dayOfWeekStr[4];
char dayStr[3];
char monthStr[4];
sprintf(dayOfWeekStr, "%s", dateTimeController.DayOfWeekShortToString());
sprintf(dayStr, "%d", day);
sprintf(monthStr, "%s", dateTimeController.MonthShortToString());
lv_label_set_text(dateDayOfWeek, dayOfWeekStr);
lv_label_set_text(dateDay, dayStr);
lv_obj_realign(dateDay);
lv_label_set_text(dateMonth, monthStr);
currentYear = year;
currentMonth = month;
currentDayOfWeek = dayOfWeek;
currentDay = day;
}
}
stepCount = motionController.NbSteps();
motionSensorOk = motionController.IsSensorOk();
if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
lv_gauge_set_value(stepGauge, 0, (stepCount.Get() / 100));
lv_obj_realign(stepGauge);
if (stepCount.Get() > settingsController.GetStepsGoal()) {
lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
}
}
return running;
}

@ -0,0 +1,86 @@
#pragma once
#include <lvgl/src/lv_core/lv_obj.h>
#include <chrono>
#include <cstdint>
#include <memory>
#include "Screen.h"
#include "ScreenList.h"
#include "components/datetime/DateTimeController.h"
namespace Pinetime {
namespace Controllers {
class Settings;
class Battery;
class Ble;
class NotificationManager;
class HeartRateController;
}
namespace Applications {
namespace Screens {
class PineTimeStyle : public Screen {
public:
PineTimeStyle(DisplayApp* app,
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
Controllers::MotionController& motionController);
~PineTimeStyle() override;
bool Refresh() override;
void OnObjectEvent(lv_obj_t* pObj, lv_event_t i);
private:
char displayedChar[5];
uint16_t currentYear = 1970;
Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown;
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
uint8_t currentDay = 0;
DirtyValue<int> batteryPercentRemaining {};
DirtyValue<bool> bleState {};
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
DirtyValue<bool> motionSensorOk {};
DirtyValue<uint32_t> stepCount {};
DirtyValue<bool> notificationState {};
lv_obj_t* timebar;
lv_obj_t* sidebar;
lv_obj_t* timeDD1;
lv_obj_t* timeDD2;
lv_obj_t* timeAMPM;
lv_obj_t* dateDayOfWeek;
lv_obj_t* dateDay;
lv_obj_t* dateMonth;
lv_obj_t* backgroundLabel;
lv_obj_t* batteryIcon;
lv_obj_t* bleIcon;
lv_obj_t* batteryPlug;
lv_obj_t* calendarOuter;
lv_obj_t* calendarInner;
lv_obj_t* calendarBar1;
lv_obj_t* calendarBar2;
lv_obj_t* calendarCrossBar1;
lv_obj_t* calendarCrossBar2;
lv_obj_t* heartbeatIcon;
lv_obj_t* heartbeatValue;
lv_obj_t* heartbeatBpm;
lv_obj_t* notificationIcon;
lv_obj_t* stepGauge;
lv_color_t needle_colors[1];
Controllers::DateTime& dateTimeController;
Controllers::Battery& batteryController;
Controllers::Ble& bleController;
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
Controllers::MotionController& motionController;
};
}
}
}

@ -58,6 +58,15 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine
lv_checkbox_set_checked(cbOption[optionsTotal], true); lv_checkbox_set_checked(cbOption[optionsTotal], true);
} }
optionsTotal++;
cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr);
lv_checkbox_set_text_static(cbOption[optionsTotal], " PineTimeStyle");
cbOption[optionsTotal]->user_data = this;
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
if (settingsController.GetClockFace() == 2) {
lv_checkbox_set_checked(cbOption[optionsTotal], true);
}
optionsTotal++; optionsTotal++;
} }

@ -417,6 +417,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) \ LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) \
LV_FONT_DECLARE(jetbrains_mono_42) \ LV_FONT_DECLARE(jetbrains_mono_42) \
LV_FONT_DECLARE(jetbrains_mono_76) \ LV_FONT_DECLARE(jetbrains_mono_76) \
LV_FONT_DECLARE(open_sans_light) \
LV_FONT_DECLARE(lv_font_sys_48) LV_FONT_DECLARE(lv_font_sys_48)
/* Enable it if you have fonts with a lot of characters. /* Enable it if you have fonts with a lot of characters.