|
| 1 | +#include "displayapp/screens/WatchFacePrime.h" |
| 2 | + |
| 3 | +#include <lvgl/lvgl.h> |
| 4 | +#include <cstdio> |
| 5 | + |
| 6 | +#include "displayapp/screens/NotificationIcon.h" |
| 7 | +#include "displayapp/screens/Symbols.h" |
| 8 | +#include "displayapp/screens/WeatherSymbols.h" |
| 9 | +#include "components/battery/BatteryController.h" |
| 10 | +#include "components/ble/BleController.h" |
| 11 | +#include "components/ble/NotificationManager.h" |
| 12 | +#include "components/heartrate/HeartRateController.h" |
| 13 | +#include "components/motion/MotionController.h" |
| 14 | +#include "components/ble/SimpleWeatherService.h" |
| 15 | +#include "components/settings/Settings.h" |
| 16 | +#include "displayapp/InfiniTimeTheme.h" |
| 17 | +#include "components/ble/MusicService.h" |
| 18 | + |
| 19 | +using namespace Pinetime::Applications::Screens; |
| 20 | + |
| 21 | +WatchFacePrime::WatchFacePrime(Controllers::DateTime& dateTimeController, |
| 22 | + const Controllers::Battery& batteryController, |
| 23 | + const Controllers::Ble& bleController, |
| 24 | + const Controllers::AlarmController& alarmController, |
| 25 | + Controllers::NotificationManager& notificationManager, |
| 26 | + Controllers::Settings& settingsController, |
| 27 | + Controllers::HeartRateController& heartRateController, |
| 28 | + Controllers::MotionController& motionController, |
| 29 | + Controllers::SimpleWeatherService& weatherService, |
| 30 | + Controllers::MusicService& music) |
| 31 | + : currentDateTime {{}}, |
| 32 | + dateTimeController {dateTimeController}, |
| 33 | + notificationManager {notificationManager}, |
| 34 | + settingsController {settingsController}, |
| 35 | + heartRateController {heartRateController}, |
| 36 | + motionController {motionController}, |
| 37 | + weatherService {weatherService}, |
| 38 | + musicService (music), |
| 39 | + statusIcons(batteryController, bleController, alarmController) { |
| 40 | + |
| 41 | + statusIcons.Create(); |
| 42 | + |
| 43 | + notificationIcon = lv_label_create(lv_scr_act(), nullptr); |
| 44 | + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); |
| 45 | + lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false)); |
| 46 | + lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); |
| 47 | + |
| 48 | + weatherIcon = lv_label_create(lv_scr_act(), nullptr); |
| 49 | + lv_obj_set_style_local_text_color(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); |
| 50 | + lv_obj_set_style_local_text_font(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &fontawesome_weathericons); |
| 51 | + lv_label_set_text_static(weatherIcon, Symbols::ban); |
| 52 | + lv_obj_align(weatherIcon, nullptr, LV_ALIGN_IN_TOP_MID, 0, 30); |
| 53 | + lv_obj_set_auto_realign(weatherIcon, true); |
| 54 | + |
| 55 | + temperature = lv_label_create(lv_scr_act(), nullptr); |
| 56 | + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); |
| 57 | + lv_label_set_text_static(temperature, "--°C"); |
| 58 | + lv_obj_align(temperature, weatherIcon, LV_ALIGN_CENTER, 0, 25); |
| 59 | + |
| 60 | + label_date = lv_label_create(lv_scr_act(), nullptr); |
| 61 | + lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 50); |
| 62 | + lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); |
| 63 | + |
| 64 | + label_music = lv_label_create(lv_scr_act(), nullptr); |
| 65 | + lv_label_set_text_fmt(label_music, "%s Not Playing", Symbols::music); |
| 66 | + lv_obj_set_style_local_text_color(label_music, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); |
| 67 | + lv_label_set_long_mode(label_music, LV_LABEL_LONG_SROLL_CIRC); |
| 68 | + lv_obj_set_width(label_music, LV_HOR_RES - 12); |
| 69 | + lv_label_set_align(label_music, LV_LABEL_ALIGN_CENTER); |
| 70 | + lv_obj_align(label_music, lv_scr_act(), LV_ALIGN_CENTER, 0, 78); |
| 71 | + |
| 72 | + label_time = lv_label_create(lv_scr_act(), nullptr); |
| 73 | + lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &prime); |
| 74 | + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); |
| 75 | + |
| 76 | + label_time_ampm = lv_label_create(lv_scr_act(), nullptr); |
| 77 | + lv_label_set_text_static(label_time_ampm, ""); |
| 78 | + lv_obj_align(label_time_ampm, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -30, -55); |
| 79 | + |
| 80 | + heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); |
| 81 | + lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat); |
| 82 | + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); |
| 83 | + lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 1); |
| 84 | + |
| 85 | + heartbeatValue = lv_label_create(lv_scr_act(), nullptr); |
| 86 | + lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xff4539)); |
| 87 | + lv_label_set_text_static(heartbeatValue, ""); |
| 88 | + lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); |
| 89 | + |
| 90 | + stepValue = lv_label_create(lv_scr_act(), nullptr); |
| 91 | + lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0a84ff)); |
| 92 | + lv_label_set_text_static(stepValue, "0"); |
| 93 | + lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); |
| 94 | + |
| 95 | + stepIcon = lv_label_create(lv_scr_act(), nullptr); |
| 96 | + lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0a84ff)); |
| 97 | + lv_label_set_text_static(stepIcon, Symbols::shoe); |
| 98 | + lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); |
| 99 | + |
| 100 | + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); |
| 101 | + Refresh(); |
| 102 | +} |
| 103 | + |
| 104 | +WatchFacePrime::~WatchFacePrime() { |
| 105 | + lv_task_del(taskRefresh); |
| 106 | + lv_obj_clean(lv_scr_act()); |
| 107 | +} |
| 108 | + |
| 109 | +void WatchFacePrime::Refresh() { |
| 110 | + statusIcons.Update(); |
| 111 | + |
| 112 | + notificationState = notificationManager.AreNewNotificationsAvailable(); |
| 113 | + if (notificationState.IsUpdated()) { |
| 114 | + lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); |
| 115 | + } |
| 116 | + |
| 117 | + currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime()); |
| 118 | + |
| 119 | + if (currentDateTime.IsUpdated()) { |
| 120 | + uint8_t hour = dateTimeController.Hours(); |
| 121 | + uint8_t minute = dateTimeController.Minutes(); |
| 122 | + |
| 123 | + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { |
| 124 | + char ampmChar[3] = "AM"; |
| 125 | + if (hour == 0) { |
| 126 | + hour = 12; |
| 127 | + } else if (hour == 12) { |
| 128 | + ampmChar[0] = 'P'; |
| 129 | + } else if (hour > 12) { |
| 130 | + hour = hour - 12; |
| 131 | + ampmChar[0] = 'P'; |
| 132 | + } |
| 133 | + lv_label_set_text(label_time_ampm, ampmChar); |
| 134 | + lv_label_set_text_fmt(label_time, "%2d:%02d", hour, minute); |
| 135 | + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); |
| 136 | + } else { |
| 137 | + lv_label_set_text_fmt(label_time, "%02d:%02d", hour, minute); |
| 138 | + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); |
| 139 | + } |
| 140 | + |
| 141 | + currentDate = std::chrono::time_point_cast<std::chrono::days>(currentDateTime.Get()); |
| 142 | + if (currentDate.IsUpdated()) { |
| 143 | + uint16_t year = dateTimeController.Year(); |
| 144 | + uint8_t day = dateTimeController.Day(); |
| 145 | + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { |
| 146 | + lv_label_set_text_fmt(label_date, |
| 147 | + "%s, %02d.%02d.%d", |
| 148 | + dateTimeController.DayOfWeekShortToStringLow(dateTimeController.DayOfWeek()), |
| 149 | + day, |
| 150 | + dateTimeController.Month(), |
| 151 | + year); |
| 152 | + } else { |
| 153 | + lv_label_set_text_fmt(label_date, |
| 154 | + "%s %s %d %d", |
| 155 | + dateTimeController.DayOfWeekShortToString(), |
| 156 | + dateTimeController.MonthShortToString(), |
| 157 | + day, |
| 158 | + year); |
| 159 | + } |
| 160 | + lv_obj_realign(label_date); |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + heartbeat = heartRateController.HeartRate(); |
| 165 | + heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; |
| 166 | + if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { |
| 167 | + if (heartbeatRunning.Get()) { |
| 168 | + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xff4539)); |
| 169 | + lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get()); |
| 170 | + } else { |
| 171 | + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B)); |
| 172 | + lv_label_set_text_static(heartbeatValue, ""); |
| 173 | + } |
| 174 | + |
| 175 | + lv_obj_realign(heartbeatIcon); |
| 176 | + lv_obj_realign(heartbeatValue); |
| 177 | + } |
| 178 | + |
| 179 | + stepCount = motionController.NbSteps(); |
| 180 | + if (stepCount.IsUpdated()) { |
| 181 | + lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get()); |
| 182 | + lv_obj_realign(stepValue); |
| 183 | + lv_obj_realign(stepIcon); |
| 184 | + } |
| 185 | + |
| 186 | + currentWeather = weatherService.Current(); |
| 187 | + if (currentWeather.IsUpdated()) { |
| 188 | + auto optCurrentWeather = currentWeather.Get(); |
| 189 | + if (optCurrentWeather) { |
| 190 | + int16_t temp = optCurrentWeather->temperature.Celsius(); |
| 191 | + char tempUnit = 'C'; |
| 192 | + if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) { |
| 193 | + temp = optCurrentWeather->temperature.Fahrenheit(); |
| 194 | + tempUnit = 'F'; |
| 195 | + } |
| 196 | + if (temp <= 0) { // freezing |
| 197 | + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); |
| 198 | + } else if (temp <= 5) { // near freezing |
| 199 | + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN); |
| 200 | + } else if (temp <= 15) { // early spring |
| 201 | + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x4db8d1)); |
| 202 | + } else if (temp <= 25) { // warm |
| 203 | + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); |
| 204 | + } else if (temp >= 25) { // hot |
| 205 | + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::deepOrange); |
| 206 | + } |
| 207 | + lv_label_set_text_fmt(temperature, "%d°%c", temp, tempUnit); |
| 208 | + lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId)); |
| 209 | + } else { |
| 210 | + lv_label_set_text_static(temperature, "--°"); |
| 211 | + lv_label_set_text(weatherIcon, Symbols::ban); |
| 212 | + } |
| 213 | + lv_obj_realign(temperature); |
| 214 | + lv_obj_realign(weatherIcon); |
| 215 | + } |
| 216 | + |
| 217 | + if (track != musicService.getTrack()) { |
| 218 | + track = musicService.getTrack(); |
| 219 | + lv_label_set_text_fmt(label_music, "%s %s", Symbols::music, track.data()); |
| 220 | + lv_obj_realign(label_music); |
| 221 | + } |
| 222 | +} |
0 commit comments