Renamed displayapp/Screens to displayapp/screens
This commit is contained in:
82
src/displayapp/screens/ApplicationList.cpp
Normal file
82
src/displayapp/screens/ApplicationList.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <DisplayApp/DisplayApp.h>
|
||||
#include <functional>
|
||||
#include "ApplicationList.h"
|
||||
#include "Tile.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp *app) :
|
||||
Screen(app),
|
||||
screens{app, {
|
||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen1(); },
|
||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen2(); },
|
||||
//[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); }
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
ApplicationList::~ApplicationList() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool ApplicationList::Refresh() {
|
||||
if(running)
|
||||
running = screens.Refresh();
|
||||
return running;
|
||||
}
|
||||
|
||||
bool ApplicationList::OnButtonPushed() {
|
||||
running = false;
|
||||
app->StartApp(Apps::Clock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
return screens.OnTouchEvent(event);
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> ApplicationList::CreateScreen1() {
|
||||
std::array<Screens::Tile::Applications, 6> applications {
|
||||
{{Symbols::clock, Apps::Clock},
|
||||
{Symbols::music, Apps::Music},
|
||||
{Symbols::sun, Apps::Brightness},
|
||||
{Symbols::list, Apps::SysInfo},
|
||||
{Symbols::check, Apps::FirmwareValidation},
|
||||
{Symbols::none, Apps::None}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
return std::unique_ptr<Screen>(new Screens::Tile(app, applications));
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
|
||||
std::array<Screens::Tile::Applications, 6> applications {
|
||||
{{Symbols::tachometer, Apps::Gauge},
|
||||
{Symbols::asterisk, Apps::Meter},
|
||||
{Symbols::paintbrush, Apps::Paint},
|
||||
{Symbols::none, Apps::None},
|
||||
{Symbols::none, Apps::None},
|
||||
{Symbols::none, Apps::None}
|
||||
}
|
||||
};
|
||||
|
||||
return std::unique_ptr<Screen>(new Screens::Tile(app, applications));
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> ApplicationList::CreateScreen3() {
|
||||
std::array<Screens::Tile::Applications, 6> applications {
|
||||
{{"A", Apps::Meter},
|
||||
{"B", Apps::Gauge},
|
||||
{"C", Apps::Clock},
|
||||
{"D", Apps::Music},
|
||||
{"E", Apps::SysInfo},
|
||||
{"F", Apps::Brightness}
|
||||
}
|
||||
};
|
||||
|
||||
return std::unique_ptr<Screen>(new Screens::Tile(app, applications));
|
||||
}
|
32
src/displayapp/screens/ApplicationList.h
Normal file
32
src/displayapp/screens/ApplicationList.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <Components/Ble/NimbleController.h>
|
||||
#include "Screen.h"
|
||||
#include "Label.h"
|
||||
#include "ScreenList.h"
|
||||
#include "Gauge.h"
|
||||
#include "Meter.h"
|
||||
#include <functional>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class ApplicationList : public Screen {
|
||||
public:
|
||||
explicit ApplicationList(DisplayApp* app);
|
||||
~ApplicationList() override;
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
private:
|
||||
bool running = true;
|
||||
|
||||
ScreenList<2> screens;
|
||||
std::unique_ptr<Screen> CreateScreen1();
|
||||
std::unique_ptr<Screen> CreateScreen2();
|
||||
std::unique_ptr<Screen> CreateScreen3();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
21
src/displayapp/screens/BatteryIcon.cpp
Normal file
21
src/displayapp/screens/BatteryIcon.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "BatteryIcon.h"
|
||||
#include "Symbols.h"
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
const char* BatteryIcon::GetBatteryIcon(float batteryPercent) {
|
||||
if(batteryPercent > 90.0f) return Symbols::batteryFull;
|
||||
if(batteryPercent > 75.0f) return Symbols::batteryThreeQuarter;
|
||||
if(batteryPercent > 50.0f) return Symbols::batteryHalf;
|
||||
if(batteryPercent > 25.0f) return Symbols::batteryOneQuarter;
|
||||
return Symbols::batteryEmpty;
|
||||
}
|
||||
|
||||
const char* BatteryIcon::GetUnknownIcon() {
|
||||
return Symbols::batteryEmpty;
|
||||
}
|
||||
|
||||
const char *BatteryIcon::GetPlugIcon(bool isCharging) {
|
||||
if(isCharging)
|
||||
return Symbols::plug;
|
||||
else return "";
|
||||
}
|
16
src/displayapp/screens/BatteryIcon.h
Normal file
16
src/displayapp/screens/BatteryIcon.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <libs/lvgl/src/lv_draw/lv_img_decoder.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class BatteryIcon {
|
||||
public:
|
||||
static const char* GetUnknownIcon();
|
||||
static const char* GetBatteryIcon(float batteryPercent);
|
||||
static const char* GetPlugIcon(bool isCharging);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
8
src/displayapp/screens/BleIcon.cpp
Normal file
8
src/displayapp/screens/BleIcon.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "BleIcon.h"
|
||||
#include "Symbols.h"
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
const char* BleIcon::GetIcon(bool isConnected) {
|
||||
if(isConnected) return Symbols::bluetooth;
|
||||
else return "";
|
||||
}
|
12
src/displayapp/screens/BleIcon.h
Normal file
12
src/displayapp/screens/BleIcon.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class BleIcon {
|
||||
public:
|
||||
static const char* GetIcon(bool isConnected);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
92
src/displayapp/screens/Brightness.cpp
Normal file
92
src/displayapp/screens/Brightness.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Brightness.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
void slider_event_cb(lv_obj_t * slider, lv_event_t event) {
|
||||
if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
auto* brightnessSlider = static_cast<Brightness*>(slider->user_data);
|
||||
brightnessSlider->OnValueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Brightness::Brightness(Pinetime::Applications::DisplayApp *app, Controllers::BrightnessController& brightness) : Screen(app), brightness{brightness} {
|
||||
slider = lv_slider_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_user_data(slider, this);
|
||||
lv_obj_set_width(slider, LV_DPI * 2);
|
||||
lv_obj_align(slider, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_event_cb(slider, slider_event_cb);
|
||||
lv_slider_set_range(slider, 0, 2);
|
||||
lv_slider_set_value(slider, LevelToInt(brightness.Level()), LV_ANIM_OFF);
|
||||
|
||||
slider_label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(slider_label, LevelToString(brightness.Level()));
|
||||
lv_obj_set_auto_realign(slider_label, true);
|
||||
lv_obj_align(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
||||
}
|
||||
|
||||
Brightness::~Brightness() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Brightness::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
||||
bool Brightness::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *Brightness::LevelToString(Pinetime::Controllers::BrightnessController::Levels level) {
|
||||
switch(level) {
|
||||
case Pinetime::Controllers::BrightnessController::Levels::Off: return "Off";
|
||||
case Pinetime::Controllers::BrightnessController::Levels::Low: return "Low";
|
||||
case Pinetime::Controllers::BrightnessController::Levels::Medium: return "Medium";
|
||||
case Pinetime::Controllers::BrightnessController::Levels::High: return "High";
|
||||
default : return "???";
|
||||
}
|
||||
}
|
||||
|
||||
void Brightness::OnValueChanged() {
|
||||
SetValue(lv_slider_get_value(slider));
|
||||
}
|
||||
|
||||
void Brightness::SetValue(uint8_t value) {
|
||||
switch(value) {
|
||||
case 0: brightness.Set(Controllers::BrightnessController::Levels::Low); break;
|
||||
case 1: brightness.Set(Controllers::BrightnessController::Levels::Medium); break;
|
||||
case 2: brightness.Set(Controllers::BrightnessController::Levels::High); break;
|
||||
}
|
||||
lv_label_set_text(slider_label, LevelToString(brightness.Level()));
|
||||
}
|
||||
|
||||
uint8_t Brightness::LevelToInt(Pinetime::Controllers::BrightnessController::Levels level) {
|
||||
switch(level) {
|
||||
case Pinetime::Controllers::BrightnessController::Levels::Off: return 0;
|
||||
case Pinetime::Controllers::BrightnessController::Levels::Low: return 0;
|
||||
case Pinetime::Controllers::BrightnessController::Levels::Medium: return 1;
|
||||
case Pinetime::Controllers::BrightnessController::Levels::High: return 2;
|
||||
default : return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Brightness::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
switch(event) {
|
||||
case TouchEvents::SwipeLeft:
|
||||
brightness.Lower();
|
||||
SetValue();
|
||||
return true;
|
||||
case TouchEvents::SwipeRight:
|
||||
brightness.Higher();
|
||||
SetValue();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Brightness::SetValue() {
|
||||
lv_slider_set_value(slider, LevelToInt(brightness.Level()), LV_ANIM_OFF);
|
||||
lv_label_set_text(slider_label, LevelToString(brightness.Level()));
|
||||
}
|
33
src/displayapp/screens/Brightness.h
Normal file
33
src/displayapp/screens/Brightness.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <Components/Brightness/BrightnessController.h>
|
||||
#include "Screen.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class Brightness : public Screen {
|
||||
public:
|
||||
Brightness(DisplayApp* app, Controllers::BrightnessController& brightness);
|
||||
~Brightness() override;
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
|
||||
void OnValueChanged();
|
||||
private:
|
||||
bool running = true;
|
||||
Controllers::BrightnessController& brightness;
|
||||
|
||||
lv_obj_t * slider_label;
|
||||
lv_obj_t * slider;
|
||||
|
||||
const char* LevelToString(Controllers::BrightnessController::Levels level);
|
||||
uint8_t LevelToInt(Controllers::BrightnessController::Levels level);
|
||||
void SetValue(uint8_t value);
|
||||
void SetValue();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
227
src/displayapp/screens/Clock.cpp
Normal file
227
src/displayapp/screens/Clock.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include <cstdio>
|
||||
#include <libs/date/includes/date/date.h>
|
||||
#include <Components/DateTime/DateTimeController.h>
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Clock.h"
|
||||
#include "../DisplayApp.h"
|
||||
#include "BatteryIcon.h"
|
||||
#include "BleIcon.h"
|
||||
#include "Symbols.h"
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
extern lv_style_t* LabelBigStyle;
|
||||
|
||||
static void event_handler(lv_obj_t * obj, lv_event_t event) {
|
||||
Clock* screen = static_cast<Clock *>(obj->user_data);
|
||||
screen->OnObjectEvent(obj, event);
|
||||
}
|
||||
|
||||
Clock::Clock(DisplayApp* app,
|
||||
Controllers::DateTime& dateTimeController,
|
||||
Controllers::Battery& batteryController,
|
||||
Controllers::Ble& bleController) : Screen(app), currentDateTime{{}},
|
||||
dateTimeController{dateTimeController}, batteryController{batteryController}, bleController{bleController} {
|
||||
displayedChar[0] = 0;
|
||||
displayedChar[1] = 0;
|
||||
displayedChar[2] = 0;
|
||||
displayedChar[3] = 0;
|
||||
displayedChar[4] = 0;
|
||||
|
||||
batteryIcon = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(batteryIcon, Symbols::batteryFull);
|
||||
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2);
|
||||
|
||||
batteryPlug = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(batteryPlug, Symbols::plug);
|
||||
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
bleIcon = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(bleIcon, Symbols::bluetooth);
|
||||
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
|
||||
label_date = lv_label_create(lv_scr_act(), NULL);
|
||||
|
||||
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);
|
||||
|
||||
label_time = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_style(label_time, LV_LABEL_STYLE_MAIN, LabelBigStyle);
|
||||
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);
|
||||
|
||||
backgroundLabel = lv_label_create(lv_scr_act(), NULL);
|
||||
backgroundLabel->user_data = this;
|
||||
lv_obj_set_click(backgroundLabel, true);
|
||||
lv_obj_set_event_cb(backgroundLabel, event_handler);
|
||||
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, "");
|
||||
|
||||
|
||||
heartbeatIcon = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(heartbeatIcon, Symbols::heartBeat);
|
||||
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
||||
|
||||
heartbeatValue = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(heartbeatValue, "0");
|
||||
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||
|
||||
heartbeatBpm = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(heartbeatBpm, "BPM");
|
||||
lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||
|
||||
stepValue = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(stepValue, "0");
|
||||
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2);
|
||||
|
||||
stepIcon = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(stepIcon, Symbols::shoe);
|
||||
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
}
|
||||
|
||||
Clock::~Clock() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Clock::Refresh() {
|
||||
batteryPercentRemaining = batteryController.PercentRemaining();
|
||||
if (batteryPercentRemaining.IsUpdated()) {
|
||||
auto batteryPercent = batteryPercentRemaining.Get();
|
||||
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
|
||||
auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent();
|
||||
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging));
|
||||
}
|
||||
|
||||
bleState = bleController.IsConnected();
|
||||
if (bleState.IsUpdated()) {
|
||||
if(bleState.Get() == true) {
|
||||
lv_label_set_text(bleIcon, BleIcon::GetIcon(true));
|
||||
} else {
|
||||
lv_label_set_text(bleIcon, BleIcon::GetIcon(false));
|
||||
}
|
||||
}
|
||||
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5);
|
||||
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
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());
|
||||
|
||||
auto hour = time.hours().count();
|
||||
auto minute = time.minutes().count();
|
||||
|
||||
char minutesChar[3];
|
||||
sprintf(minutesChar, "%02d", static_cast<int>(minute));
|
||||
|
||||
char hoursChar[3];
|
||||
sprintf(hoursChar, "%02d", static_cast<int>(hour));
|
||||
|
||||
char timeStr[6];
|
||||
sprintf(timeStr, "%c%c:%c%c", hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);
|
||||
|
||||
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];
|
||||
|
||||
lv_label_set_text(label_time, timeStr);
|
||||
}
|
||||
|
||||
if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {
|
||||
char dateStr[22];
|
||||
sprintf(dateStr, "%s %d %s %d", DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);
|
||||
lv_label_set_text(label_date, dateStr);
|
||||
|
||||
|
||||
currentYear = year;
|
||||
currentMonth = month;
|
||||
currentDayOfWeek = dayOfWeek;
|
||||
currentDay = day;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO heartbeat = heartBeatController.GetValue();
|
||||
if(heartbeat.IsUpdated()) {
|
||||
char heartbeatBuffer[4];
|
||||
sprintf(heartbeatBuffer, "%d", heartbeat.Get());
|
||||
lv_label_set_text(heartbeatValue, heartbeatBuffer);
|
||||
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
||||
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||
lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||
}
|
||||
|
||||
// TODO stepCount = stepController.GetValue();
|
||||
if(stepCount.IsUpdated()) {
|
||||
char stepBuffer[5];
|
||||
sprintf(stepBuffer, "%lu", stepCount.Get());
|
||||
lv_label_set_text(stepValue, stepBuffer);
|
||||
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2);
|
||||
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
}
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
const char *Clock::MonthToString(Pinetime::Controllers::DateTime::Months month) {
|
||||
return Clock::MonthsString[static_cast<uint8_t>(month)];
|
||||
}
|
||||
|
||||
const char *Clock::DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek) {
|
||||
return Clock::DaysString[static_cast<uint8_t>(dayOfWeek)];
|
||||
}
|
||||
|
||||
char const *Clock::DaysString[] = {
|
||||
"",
|
||||
"MONDAY",
|
||||
"TUESDAY",
|
||||
"WEDNESDAY",
|
||||
"THURSDAY",
|
||||
"FRIDAY",
|
||||
"SATURDAY",
|
||||
"SUNDAY"
|
||||
};
|
||||
|
||||
char const *Clock::MonthsString[] = {
|
||||
"",
|
||||
"JAN",
|
||||
"FEB",
|
||||
"MAR",
|
||||
"APR",
|
||||
"MAY",
|
||||
"JUN",
|
||||
"JUL",
|
||||
"AUG",
|
||||
"SEP",
|
||||
"OCT",
|
||||
"NOV",
|
||||
"DEC"
|
||||
};
|
||||
|
||||
void Clock::OnObjectEvent(lv_obj_t *obj, lv_event_t event) {
|
||||
if(obj == backgroundLabel) {
|
||||
if (event == LV_EVENT_CLICKED) {
|
||||
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Clock::OnButtonPushed() {
|
||||
running = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
88
src/displayapp/screens/Clock.h
Normal file
88
src/displayapp/screens/Clock.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <Components/Battery/BatteryController.h>
|
||||
#include <Components/Ble/BleController.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
template <class T>
|
||||
class DirtyValue {
|
||||
public:
|
||||
explicit DirtyValue(T v) { value = v; }
|
||||
explicit DirtyValue(T& v) { value = v; }
|
||||
bool IsUpdated() const { return isUpdated; }
|
||||
T& Get() { this->isUpdated = false; return value; }
|
||||
|
||||
DirtyValue& operator=(const T& other) {
|
||||
if (this->value != other) {
|
||||
this->value = other;
|
||||
this->isUpdated = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
T value;
|
||||
bool isUpdated = true;
|
||||
};
|
||||
class Clock : public Screen{
|
||||
public:
|
||||
Clock(DisplayApp* app,
|
||||
Controllers::DateTime& dateTimeController,
|
||||
Controllers::Battery& batteryController,
|
||||
Controllers::Ble& bleController);
|
||||
~Clock() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
void OnObjectEvent(lv_obj_t *pObj, lv_event_t i);
|
||||
private:
|
||||
static const char* MonthToString(Pinetime::Controllers::DateTime::Months month);
|
||||
static const char* DayOfWeekToString(Pinetime::Controllers::DateTime::Days dayOfWeek);
|
||||
static char const *DaysString[];
|
||||
static char const *MonthsString[];
|
||||
|
||||
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<float> batteryPercentRemaining {0};
|
||||
DirtyValue<bool> bleState {false};
|
||||
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime;
|
||||
DirtyValue<uint32_t> stepCount {0};
|
||||
DirtyValue<uint8_t> heartbeat {0};
|
||||
|
||||
|
||||
lv_obj_t* label_time;
|
||||
lv_obj_t* label_date;
|
||||
lv_obj_t* backgroundLabel;
|
||||
lv_obj_t * batteryIcon;
|
||||
lv_obj_t * bleIcon;
|
||||
lv_obj_t* batteryPlug;
|
||||
lv_obj_t* heartbeatIcon;
|
||||
lv_obj_t* heartbeatValue;
|
||||
lv_obj_t* heartbeatBpm;
|
||||
lv_obj_t* stepIcon;
|
||||
lv_obj_t* stepValue;
|
||||
|
||||
Controllers::DateTime& dateTimeController;
|
||||
Controllers::Battery& batteryController;
|
||||
Controllers::Ble& bleController;
|
||||
|
||||
bool running = true;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
64
src/displayapp/screens/DropDownDemo.cpp
Normal file
64
src/displayapp/screens/DropDownDemo.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <libraries/log/nrf_log.h>
|
||||
#include "DropDownDemo.h"
|
||||
#include "../DisplayApp.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
DropDownDemo::DropDownDemo(Pinetime::Applications::DisplayApp *app) : Screen(app) {
|
||||
// Create the dropdown object, with many item, and fix its height
|
||||
ddlist = lv_ddlist_create(lv_scr_act(), NULL);
|
||||
lv_ddlist_set_options(ddlist, "Apple\n"
|
||||
"Banana\n"
|
||||
"Orange\n"
|
||||
"Melon\n"
|
||||
"Grape\n"
|
||||
"Raspberry\n"
|
||||
"A\n"
|
||||
"B\n"
|
||||
"C\n"
|
||||
"D\n"
|
||||
"E");
|
||||
lv_ddlist_set_fix_width(ddlist, 150);
|
||||
lv_ddlist_set_draw_arrow(ddlist, true);
|
||||
lv_ddlist_set_fix_height(ddlist, 150);
|
||||
lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, 0, 20);
|
||||
}
|
||||
|
||||
DropDownDemo::~DropDownDemo() {
|
||||
// Reset the touchmode
|
||||
app->SetTouchMode(DisplayApp::TouchModes::Gestures);
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool DropDownDemo::Refresh() {
|
||||
auto* list = static_cast<lv_ddlist_ext_t *>(ddlist->ext_attr);
|
||||
|
||||
// Switch touchmode to Polling if the dropdown is opened. This will allow to scroll inside the
|
||||
// dropdown while it is opened.
|
||||
// Disable the polling mode when the dropdown is closed to be able to handle the gestures.
|
||||
if(list->opened)
|
||||
app->SetTouchMode(DisplayApp::TouchModes::Polling);
|
||||
else
|
||||
app->SetTouchMode(DisplayApp::TouchModes::Gestures);
|
||||
return running;
|
||||
}
|
||||
|
||||
bool DropDownDemo::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DropDownDemo::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
// If the dropdown is opened, notify Display app that it doesn't need to handle the event
|
||||
// (this will prevent displayApp from going back to the menu or clock scree).
|
||||
auto* list = static_cast<lv_ddlist_ext_t *>(ddlist->ext_attr);
|
||||
if(list->opened) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
29
src/displayapp/screens/DropDownDemo.h
Normal file
29
src/displayapp/screens/DropDownDemo.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class DropDownDemo : public Screen{
|
||||
public:
|
||||
DropDownDemo(DisplayApp* app);
|
||||
~DropDownDemo() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
|
||||
private:
|
||||
lv_obj_t * ddlist;
|
||||
bool running = true;
|
||||
bool isDropDownOpened = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
82
src/displayapp/screens/FirmwareUpdate.cpp
Normal file
82
src/displayapp/screens/FirmwareUpdate.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "FirmwareUpdate.h"
|
||||
#include "../DisplayApp.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
|
||||
FirmwareUpdate::FirmwareUpdate(Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::Ble& bleController) :
|
||||
Screen(app), bleController{bleController} {
|
||||
|
||||
titleLabel = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(titleLabel, "Firmware update");
|
||||
lv_obj_set_auto_realign(titleLabel, true);
|
||||
lv_obj_align(titleLabel, NULL, LV_ALIGN_IN_TOP_MID, 0, 50);
|
||||
|
||||
bar1 = lv_bar_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_size(bar1, 200, 30);
|
||||
lv_obj_align(bar1, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_bar_set_anim_time(bar1, 10);
|
||||
lv_bar_set_range(bar1, 0, 100);
|
||||
lv_bar_set_value(bar1, 0, LV_ANIM_OFF);
|
||||
|
||||
percentLabel = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_text(percentLabel, "");
|
||||
lv_obj_set_auto_realign(percentLabel, true);
|
||||
lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60);
|
||||
}
|
||||
|
||||
FirmwareUpdate::~FirmwareUpdate() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::Refresh() {
|
||||
switch(bleController.State()) {
|
||||
default:
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Idle:
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Running:
|
||||
if(state != States::Running)
|
||||
state = States::Running;
|
||||
return DisplayProgression();
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated:
|
||||
if(state != States::Validated) {
|
||||
UpdateValidated();
|
||||
state = States::Validated;
|
||||
}
|
||||
return running;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Error:
|
||||
if(state != States::Error) {
|
||||
UpdateError();
|
||||
state = States::Error;
|
||||
}
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::DisplayProgression() const {
|
||||
float current = bleController.FirmwareUpdateCurrentBytes() / 1024.0f;
|
||||
float total = bleController.FirmwareUpdateTotalBytes() / 1024.0f;
|
||||
int16_t pc = (current / total) * 100.0f;
|
||||
sprintf(percentStr, "%d %%", pc);
|
||||
lv_label_set_text(percentLabel, percentStr);
|
||||
|
||||
lv_bar_set_value(bar1, pc, LV_ANIM_OFF);
|
||||
return running;
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FirmwareUpdate::UpdateValidated() {
|
||||
lv_label_set_recolor(percentLabel, true);
|
||||
lv_label_set_text(percentLabel, "#00ff00 Image Ok!#");
|
||||
}
|
||||
|
||||
void FirmwareUpdate::UpdateError() {
|
||||
lv_label_set_recolor(percentLabel, true);
|
||||
lv_label_set_text(percentLabel, "#ff0000 Error!#");
|
||||
}
|
41
src/displayapp/screens/FirmwareUpdate.h
Normal file
41
src/displayapp/screens/FirmwareUpdate.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <Components/Ble/BleController.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class FirmwareUpdate : public Screen{
|
||||
public:
|
||||
FirmwareUpdate(DisplayApp* app, Pinetime::Controllers::Ble& bleController);
|
||||
~FirmwareUpdate() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
private:
|
||||
enum class States { Idle, Running, Validated, Error };
|
||||
Pinetime::Controllers::Ble& bleController;
|
||||
lv_obj_t* bar1;
|
||||
lv_obj_t* percentLabel;
|
||||
lv_obj_t* titleLabel;
|
||||
mutable char percentStr[10];
|
||||
bool running = true;
|
||||
States state;
|
||||
|
||||
bool DisplayProgression() const;
|
||||
|
||||
void UpdateValidated();
|
||||
|
||||
void UpdateError();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
91
src/displayapp/screens/FirmwareValidation.cpp
Normal file
91
src/displayapp/screens/FirmwareValidation.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "FirmwareValidation.h"
|
||||
#include "../DisplayApp.h"
|
||||
#include "../../Version.h"
|
||||
#include "../../Components/FirmwareValidator/FirmwareValidator.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
namespace {
|
||||
static void ButtonEventHandler(lv_obj_t * obj, lv_event_t event)
|
||||
{
|
||||
FirmwareValidation* screen = static_cast<FirmwareValidation *>(obj->user_data);
|
||||
screen->OnButtonEvent(obj, event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp *app,
|
||||
Pinetime::Controllers::FirmwareValidator &validator)
|
||||
: Screen{app}, validator{validator} {
|
||||
labelVersionInfo = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_obj_align(labelVersionInfo, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
lv_label_set_text(labelVersionInfo, "Version : ");
|
||||
lv_label_set_align(labelVersionInfo, LV_LABEL_ALIGN_LEFT);
|
||||
|
||||
|
||||
labelVersionValue = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_obj_align(labelVersionValue, labelVersionInfo, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||
lv_label_set_recolor(labelVersionValue, true);
|
||||
sprintf(version, "%ld.%ld.%ld", Version::Major(), Version::Minor(), Version::Patch());
|
||||
lv_label_set_text(labelVersionValue, version);
|
||||
|
||||
labelIsValidated = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_obj_align(labelIsValidated, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 50);
|
||||
lv_label_set_recolor(labelIsValidated, true);
|
||||
lv_label_set_long_mode(labelIsValidated, LV_LABEL_LONG_BREAK);
|
||||
lv_obj_set_width(labelIsValidated, 240);
|
||||
|
||||
if(validator.IsValidated())
|
||||
lv_label_set_text(labelIsValidated, "You have already\n#00ff00 validated# this firmware#");
|
||||
else {
|
||||
lv_label_set_text(labelIsValidated,
|
||||
"Please #00ff00 Validate# this version or\n#ff0000 Reset# to rollback to the previous version.");
|
||||
|
||||
buttonValidate = lv_btn_create(lv_scr_act(), NULL);
|
||||
lv_obj_align(buttonValidate, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
|
||||
buttonValidate->user_data = this;
|
||||
lv_obj_set_event_cb(buttonValidate, ButtonEventHandler);
|
||||
|
||||
labelButtonValidate = lv_label_create(buttonValidate, NULL);
|
||||
lv_label_set_recolor(labelButtonValidate, true);
|
||||
lv_label_set_text(labelButtonValidate, "#00ff00 Validate#");
|
||||
|
||||
buttonReset = lv_btn_create(lv_scr_act(), NULL);
|
||||
buttonReset->user_data = this;
|
||||
lv_obj_align(buttonReset, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
|
||||
lv_obj_set_event_cb(buttonReset, ButtonEventHandler);
|
||||
|
||||
labelButtonReset = lv_label_create(buttonReset, NULL);
|
||||
lv_label_set_recolor(labelButtonReset, true);
|
||||
lv_label_set_text(labelButtonReset, "#ff0000 Reset#");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FirmwareValidation::~FirmwareValidation() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool FirmwareValidation::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
||||
bool FirmwareValidation::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FirmwareValidation::OnButtonEvent(lv_obj_t *object, lv_event_t event) {
|
||||
if(object == buttonValidate && event == LV_EVENT_PRESSED) {
|
||||
validator.Validate();
|
||||
running = false;
|
||||
} else if(object == buttonReset && event == LV_EVENT_PRESSED) {
|
||||
validator.Reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
42
src/displayapp/screens/FirmwareValidation.h
Normal file
42
src/displayapp/screens/FirmwareValidation.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class FirmwareValidator;
|
||||
}
|
||||
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class FirmwareValidation : public Screen{
|
||||
public:
|
||||
FirmwareValidation(DisplayApp* app, Pinetime::Controllers::FirmwareValidator& validator);
|
||||
~FirmwareValidation() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
void OnButtonEvent(lv_obj_t *object, lv_event_t event);
|
||||
|
||||
private:
|
||||
Pinetime::Controllers::FirmwareValidator& validator;
|
||||
|
||||
lv_obj_t* labelVersionInfo;
|
||||
lv_obj_t* labelVersionValue;
|
||||
char version[9];
|
||||
lv_obj_t* labelIsValidated;
|
||||
lv_obj_t* buttonValidate;
|
||||
lv_obj_t* labelButtonValidate;
|
||||
lv_obj_t* buttonReset;
|
||||
lv_obj_t* labelButtonReset;
|
||||
bool running = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
58
src/displayapp/screens/Gauge.cpp
Normal file
58
src/displayapp/screens/Gauge.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Gauge.h"
|
||||
#include "../DisplayApp.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
|
||||
Gauge::Gauge(Pinetime::Applications::DisplayApp *app) : Screen(app) {
|
||||
/*Create a style*/
|
||||
lv_style_copy(&style, &lv_style_pretty_color);
|
||||
style.body.main_color = LV_COLOR_CYAN; /*Line color at the beginning*/
|
||||
style.body.grad_color = LV_COLOR_RED; /*Line color at the end*/
|
||||
style.body.padding.left = 10; /*Scale line length*/
|
||||
style.body.padding.inner = 8 ; /*Scale label padding*/
|
||||
style.body.border.color = lv_color_hex3(0x333); /*Needle middle circle color*/
|
||||
style.line.width = 3;
|
||||
style.text.color = LV_COLOR_WHITE;
|
||||
style.line.color = LV_COLOR_RED; /*Line color after the critical value*/
|
||||
|
||||
|
||||
/*Describe the color for the needles*/
|
||||
|
||||
needle_colors[0] = LV_COLOR_ORANGE;
|
||||
|
||||
/*Create a gauge*/
|
||||
gauge1 = lv_gauge_create(lv_scr_act(), NULL);
|
||||
lv_gauge_set_style(gauge1, LV_GAUGE_STYLE_MAIN, &style);
|
||||
lv_gauge_set_needle_count(gauge1, 1, needle_colors);
|
||||
lv_obj_set_size(gauge1, 180, 180);
|
||||
lv_obj_align(gauge1, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_gauge_set_scale(gauge1, 360, 60, 0);
|
||||
lv_gauge_set_range(gauge1, 0, 59);
|
||||
|
||||
/*Set the values*/
|
||||
lv_gauge_set_value(gauge1, 0, value);
|
||||
}
|
||||
|
||||
Gauge::~Gauge() {
|
||||
|
||||
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Gauge::Refresh() {
|
||||
// lv_lmeter_set_value(lmeter, value++); /*Set the current value*/
|
||||
// if(value>=60) value = 0;
|
||||
|
||||
lv_gauge_set_value(gauge1, 0, value++);
|
||||
if(value == 59) value = 0;
|
||||
return running;
|
||||
}
|
||||
|
||||
bool Gauge::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
32
src/displayapp/screens/Gauge.h
Normal file
32
src/displayapp/screens/Gauge.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class Gauge : public Screen{
|
||||
public:
|
||||
Gauge(DisplayApp* app);
|
||||
~Gauge() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
private:
|
||||
lv_style_t style;
|
||||
lv_color_t needle_colors[3];
|
||||
lv_obj_t * gauge1;
|
||||
|
||||
uint32_t value=30;
|
||||
bool running = true;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
44
src/displayapp/screens/InfiniPaint.cpp
Normal file
44
src/displayapp/screens/InfiniPaint.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <libraries/log/nrf_log.h>
|
||||
#include "InfiniPaint.h"
|
||||
#include "../DisplayApp.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp *app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl{lvgl} {
|
||||
app->SetTouchMode(DisplayApp::TouchModes::Polling);
|
||||
std::fill(b, b+bufferSize, LV_COLOR_WHITE);
|
||||
}
|
||||
|
||||
InfiniPaint::~InfiniPaint() {
|
||||
// Reset the touchmode
|
||||
app->SetTouchMode(DisplayApp::TouchModes::Gestures);
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool InfiniPaint::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
||||
bool InfiniPaint::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InfiniPaint::OnTouchEvent(uint16_t x, uint16_t y) {
|
||||
lv_area_t area;
|
||||
area.x1 = x-(width/2);
|
||||
area.y1 = y-(height/2);
|
||||
area.x2 = x+(width/2)-1;
|
||||
area.y2 = y+(height/2)-1;
|
||||
lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::None);
|
||||
lvgl.FlushDisplay(&area, b);
|
||||
return true;
|
||||
}
|
||||
|
35
src/displayapp/screens/InfiniPaint.h
Normal file
35
src/displayapp/screens/InfiniPaint.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <drivers/St7789.h>
|
||||
#include <DisplayApp/LittleVgl.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class InfiniPaint : public Screen{
|
||||
public:
|
||||
InfiniPaint(DisplayApp* app, Pinetime::Components::LittleVgl& lvgl);
|
||||
~InfiniPaint() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
bool OnTouchEvent(uint16_t x, uint16_t y) override;
|
||||
|
||||
private:
|
||||
Pinetime::Components::LittleVgl& lvgl;
|
||||
static constexpr uint16_t width = 10;
|
||||
static constexpr uint16_t height = 10;
|
||||
static constexpr uint16_t bufferSize = width*height;
|
||||
lv_color_t b[bufferSize];
|
||||
bool running = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
15
src/displayapp/screens/Label.cpp
Normal file
15
src/displayapp/screens/Label.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Label.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
Label::Label(Pinetime::Applications::DisplayApp *app, const char *text) : Screen(app), text{text} {
|
||||
label = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_align(label, LV_LABEL_ALIGN_LEFT);
|
||||
lv_obj_set_size(label, 240, 240);
|
||||
lv_label_set_text(label, text);
|
||||
}
|
||||
|
||||
Label::~Label() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
23
src/displayapp/screens/Label.h
Normal file
23
src/displayapp/screens/Label.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "Screen.h"
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class Label : public Screen {
|
||||
public:
|
||||
Label(DisplayApp* app, const char* text);
|
||||
~Label() override;
|
||||
bool Refresh() override {return false;}
|
||||
|
||||
private:
|
||||
lv_obj_t * label = nullptr;
|
||||
const char* text = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
47
src/displayapp/screens/Meter.cpp
Normal file
47
src/displayapp/screens/Meter.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Meter.h"
|
||||
#include "../DisplayApp.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
|
||||
Meter::Meter(Pinetime::Applications::DisplayApp *app) : Screen(app) {
|
||||
|
||||
lv_style_copy(&style_lmeter, &lv_style_pretty_color);
|
||||
style_lmeter.line.width = 2;
|
||||
style_lmeter.line.color = LV_COLOR_SILVER;
|
||||
style_lmeter.body.main_color = lv_color_make(255,0,0);
|
||||
style_lmeter.body.grad_color = lv_color_make(160,0,0);
|
||||
style_lmeter.body.padding.left = 16; /*Line length*/
|
||||
|
||||
/*Create a line meter */
|
||||
lmeter = lv_lmeter_create(lv_scr_act(), NULL);
|
||||
lv_lmeter_set_range(lmeter, 0, 60); /*Set the range*/
|
||||
lv_lmeter_set_value(lmeter, value); /*Set the current value*/
|
||||
lv_lmeter_set_angle_offset(lmeter, 180);
|
||||
lv_lmeter_set_scale(lmeter, 360, 60); /*Set the angle and number of lines*/
|
||||
lv_lmeter_set_style(lmeter, LV_LMETER_STYLE_MAIN, &style_lmeter); /*Apply the new style*/
|
||||
lv_obj_set_size(lmeter, 150, 150);
|
||||
lv_obj_align(lmeter, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
Meter::~Meter() {
|
||||
|
||||
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Meter::Refresh() {
|
||||
lv_lmeter_set_value(lmeter, value++); /*Set the current value*/
|
||||
if(value>=60) value = 0;
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
bool Meter::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
32
src/displayapp/screens/Meter.h
Normal file
32
src/displayapp/screens/Meter.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class Meter : public Screen{
|
||||
public:
|
||||
Meter(DisplayApp* app);
|
||||
~Meter() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
private:
|
||||
lv_style_t style_lmeter;
|
||||
lv_obj_t * lmeter;
|
||||
|
||||
uint32_t value=0;
|
||||
bool running = true;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
81
src/displayapp/screens/Modal.cpp
Normal file
81
src/displayapp/screens/Modal.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Modal.h"
|
||||
#include "../DisplayApp.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
Modal::Modal(Pinetime::Applications::DisplayApp *app) : Screen(app) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
Modal::~Modal() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Modal::Refresh() {
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
bool Modal::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Modal::Hide() {
|
||||
/* Delete the parent modal background */
|
||||
lv_obj_del_async(lv_obj_get_parent(mbox));
|
||||
mbox = NULL; /* happens before object is actually deleted! */
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
void Modal::mbox_event_cb(lv_obj_t *obj, lv_event_t evt) {
|
||||
auto* m = static_cast<Modal *>(obj->user_data);
|
||||
m->OnEvent(obj, evt);
|
||||
}
|
||||
|
||||
void Modal::OnEvent(lv_obj_t *event_obj, lv_event_t evt) {
|
||||
if(evt == LV_EVENT_DELETE && event_obj == mbox) {
|
||||
Hide();
|
||||
} else if(evt == LV_EVENT_VALUE_CHANGED) {
|
||||
/* A button was clicked */
|
||||
lv_mbox_start_auto_close(mbox, 0);
|
||||
// Hide();
|
||||
}
|
||||
}
|
||||
|
||||
void Modal::Show(const char* msg) {
|
||||
if(isVisible) return;
|
||||
isVisible = true;
|
||||
lv_style_copy(&modal_style, &lv_style_plain_color);
|
||||
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
|
||||
modal_style.body.opa = LV_OPA_50;
|
||||
|
||||
obj = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(obj, &modal_style);
|
||||
lv_obj_set_pos(obj, 0, 0);
|
||||
lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES);
|
||||
lv_obj_set_opa_scale_enable(obj, true); /* Enable opacity scaling for the animation */
|
||||
|
||||
static const char * btns2[] = {"Ok", ""};
|
||||
|
||||
/* Create the message box as a child of the modal background */
|
||||
mbox = lv_mbox_create(obj, NULL);
|
||||
lv_mbox_add_btns(mbox, btns2);
|
||||
lv_mbox_set_text(mbox, msg);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_event_cb(mbox, Modal::mbox_event_cb);
|
||||
|
||||
mbox->user_data = this;
|
||||
|
||||
/* Fade the message box in with an animation */
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_time(&a, 500, 0);
|
||||
lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||
lv_anim_set_exec_cb(&a, obj, (lv_anim_exec_xcb_t)lv_obj_set_opa_scale);
|
||||
lv_anim_create(&a);
|
||||
}
|
39
src/displayapp/screens/Modal.h
Normal file
39
src/displayapp/screens/Modal.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class Modal : public Screen{
|
||||
public:
|
||||
Modal(DisplayApp* app);
|
||||
~Modal() override;
|
||||
|
||||
void Show(const char* msg);
|
||||
void Hide();
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
static void mbox_event_cb(lv_obj_t *obj, lv_event_t evt);
|
||||
private:
|
||||
void OnEvent(lv_obj_t *event_obj, lv_event_t evt);
|
||||
|
||||
lv_style_t modal_style;
|
||||
lv_obj_t *obj;
|
||||
lv_obj_t *mbox;
|
||||
lv_obj_t *info;
|
||||
bool running = true;
|
||||
bool isVisible = false;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
125
src/displayapp/screens/Music.cpp
Normal file
125
src/displayapp/screens/Music.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Music.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
extern lv_font_t jetbrains_mono_extrabold_compressed;
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
static void event_handler(lv_obj_t * obj, lv_event_t event)
|
||||
{
|
||||
Music* screen = static_cast<Music *>(obj->user_data);
|
||||
screen->OnObjectEvent(obj, event);
|
||||
}
|
||||
|
||||
Music::Music(Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::MusicService &music) : Screen(app), musicService(music) {
|
||||
lv_obj_t * label;
|
||||
|
||||
btnVolDown = lv_btn_create(lv_scr_act(), NULL);
|
||||
btnVolDown->user_data = this;
|
||||
lv_obj_set_event_cb(btnVolDown, event_handler);
|
||||
lv_obj_align(btnVolDown, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);
|
||||
label = lv_label_create(btnVolDown, NULL);
|
||||
lv_label_set_text(label, "v-");
|
||||
|
||||
btnVolUp = lv_btn_create(lv_scr_act(), NULL);
|
||||
btnVolUp->user_data = this;
|
||||
lv_obj_set_event_cb(btnVolUp, event_handler);
|
||||
lv_obj_align(btnVolUp, NULL, LV_ALIGN_IN_TOP_RIGHT, -10, 10);
|
||||
label = lv_label_create(btnVolUp, NULL);
|
||||
lv_label_set_text(label, "v+");
|
||||
|
||||
btnPrev = lv_btn_create(lv_scr_act(), NULL);
|
||||
btnPrev->user_data = this;
|
||||
lv_obj_set_event_cb(btnPrev, event_handler);
|
||||
lv_obj_set_size(btnPrev, LV_HOR_RES / 4, LV_VER_RES / 4);
|
||||
lv_obj_align(btnPrev, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 10,-10);
|
||||
label = lv_label_create(btnPrev, NULL);
|
||||
lv_label_set_text(label, "<<");
|
||||
|
||||
btnPlayPause = lv_btn_create(lv_scr_act(), NULL);
|
||||
btnPlayPause->user_data = this;
|
||||
lv_obj_set_event_cb(btnPlayPause, event_handler);
|
||||
lv_obj_set_size(btnPlayPause, LV_HOR_RES / 4, LV_VER_RES / 4);
|
||||
lv_obj_align(btnPlayPause, NULL, LV_ALIGN_IN_BOTTOM_MID, 0,-10);
|
||||
txtPlayPause = lv_label_create(btnPlayPause, NULL);
|
||||
lv_label_set_text(txtPlayPause, ">");
|
||||
|
||||
btnNext = lv_btn_create(lv_scr_act(), NULL);
|
||||
btnNext->user_data = this;
|
||||
lv_obj_set_event_cb(btnNext, event_handler);
|
||||
lv_obj_set_size(btnNext, LV_HOR_RES / 4, LV_VER_RES / 4);
|
||||
lv_obj_align(btnNext, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -10,-10);
|
||||
label = lv_label_create(btnNext, NULL);
|
||||
lv_label_set_text(label, ">>");
|
||||
|
||||
txtArtist = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL);
|
||||
lv_obj_align(txtArtist, NULL, LV_ALIGN_IN_LEFT_MID, 0,-20);
|
||||
lv_label_set_text(txtArtist, "Artist Name");
|
||||
lv_label_set_align(txtArtist, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_set_width(txtArtist, LV_HOR_RES);
|
||||
|
||||
txtTrack = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_DOT);
|
||||
lv_obj_align(txtTrack, NULL, LV_ALIGN_IN_LEFT_MID, 0,20);
|
||||
lv_label_set_text(txtTrack, "This is a very long track name");
|
||||
lv_label_set_align(txtTrack, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_set_width(txtTrack, LV_HOR_RES);
|
||||
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN);
|
||||
}
|
||||
|
||||
Music::~Music() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Music::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Music::Refresh() {
|
||||
|
||||
if (m_artist != musicService.artist()) {
|
||||
m_artist = musicService.artist();
|
||||
lv_label_set_text(txtArtist, m_artist.data());
|
||||
}
|
||||
if (m_track != musicService.track()) {
|
||||
m_track = musicService.track();
|
||||
lv_label_set_text(txtTrack, m_track.data());
|
||||
}
|
||||
if (m_album != musicService.album()) {
|
||||
m_album = musicService.album();
|
||||
}
|
||||
if (m_status != musicService.status()) {
|
||||
m_status = musicService.status();
|
||||
}
|
||||
if (m_status == Pinetime::Controllers::MusicService::STATUS_MUSIC_PLAYING) {
|
||||
lv_label_set_text(txtPlayPause, "||");
|
||||
} else {
|
||||
lv_label_set_text(txtPlayPause, ">");
|
||||
}
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event)
|
||||
{
|
||||
if (event == LV_EVENT_CLICKED) {
|
||||
if (obj == btnVolDown) {
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_VOLDOWN);
|
||||
} else if (obj == btnVolUp) {
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_VOLUP);
|
||||
} else if (obj == btnPrev) {
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_PREV);
|
||||
} else if (obj == btnPlayPause) {
|
||||
if (m_status == Pinetime::Controllers::MusicService::STATUS_MUSIC_PLAYING) {
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_PAUSE);
|
||||
} else {
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_PLAY);
|
||||
}
|
||||
} else if (obj == btnNext) {
|
||||
musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT);
|
||||
}
|
||||
}
|
||||
}
|
49
src/displayapp/screens/Music.h
Normal file
49
src/displayapp/screens/Music.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include <Components/Gfx/Gfx.h>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_style.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <Components/Battery/BatteryController.h>
|
||||
#include <Components/Ble/BleController.h>
|
||||
#include "../../Version.h"
|
||||
#include <Components/Ble/MusicService.h>
|
||||
#include <string>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class Music : public Screen{
|
||||
public:
|
||||
Music(DisplayApp* app, Pinetime::Controllers::MusicService &music);
|
||||
~Music() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
void OnObjectEvent(lv_obj_t* obj, lv_event_t event);
|
||||
|
||||
private:
|
||||
lv_obj_t * btnPrev;
|
||||
lv_obj_t * btnPlayPause;
|
||||
lv_obj_t * btnNext;
|
||||
lv_obj_t * btnVolDown;
|
||||
lv_obj_t * btnVolUp;
|
||||
lv_obj_t * txtArtist;
|
||||
lv_obj_t * txtTrack;
|
||||
lv_obj_t * txtPlayPause;
|
||||
|
||||
bool running = true;
|
||||
Pinetime::Controllers::MusicService &musicService;
|
||||
std::string m_artist;
|
||||
std::string m_album;
|
||||
std::string m_track;
|
||||
unsigned char m_status;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
2
src/displayapp/screens/Screen.cpp
Normal file
2
src/displayapp/screens/Screen.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "Screen.h"
|
||||
using namespace Pinetime::Applications::Screens;
|
30
src/displayapp/screens/Screen.h
Normal file
30
src/displayapp/screens/Screen.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "../TouchEvents.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
class DisplayApp;
|
||||
namespace Screens {
|
||||
class Screen {
|
||||
public:
|
||||
Screen(DisplayApp* app) : app{app} {}
|
||||
virtual ~Screen() = default;
|
||||
|
||||
// Return false if the app can be closed, true if it must continue to run
|
||||
virtual bool Refresh() = 0;
|
||||
|
||||
// Return false if the button hasn't been handled by the app, true if it has been handled
|
||||
virtual bool OnButtonPushed() { return false; }
|
||||
|
||||
// Return false if the event hasn't been handled by the app, true if it has been handled
|
||||
virtual bool OnTouchEvent(TouchEvents event) { return false; }
|
||||
virtual bool OnTouchEvent(uint16_t x, uint16_t y) { return false; }
|
||||
|
||||
protected:
|
||||
DisplayApp* app;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
66
src/displayapp/screens/ScreenList.h
Normal file
66
src/displayapp/screens/ScreenList.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <Components/Ble/NimbleController.h>
|
||||
#include <functional>
|
||||
#include "Screen.h"
|
||||
#include "Label.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
template <size_t N>
|
||||
class ScreenList : public Screen {
|
||||
public:
|
||||
ScreenList(DisplayApp* app, std::array<std::function<std::unique_ptr<Screen>()>, N>&& screens)
|
||||
: Screen(app), screens{std::move(screens)}, current{this->screens[0]()} {
|
||||
|
||||
}
|
||||
|
||||
~ScreenList() override {
|
||||
|
||||
}
|
||||
|
||||
bool Refresh() override {
|
||||
running = current->Refresh();
|
||||
return running;
|
||||
}
|
||||
|
||||
bool OnButtonPushed() override {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnTouchEvent(TouchEvents event) override {
|
||||
switch (event) {
|
||||
case TouchEvents::SwipeDown:
|
||||
if (screenIndex > 0) {
|
||||
current.reset(nullptr);
|
||||
app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down);
|
||||
screenIndex--;
|
||||
current = screens[screenIndex]();
|
||||
}
|
||||
return true;
|
||||
case TouchEvents::SwipeUp:
|
||||
if (screenIndex < screens.size() - 1) {
|
||||
current.reset(nullptr);
|
||||
app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up);
|
||||
screenIndex++;
|
||||
current = screens[screenIndex]();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool running = true;
|
||||
uint8_t screenIndex = 0;
|
||||
std::array<std::function<std::unique_ptr<Screen>()>, N> screens;
|
||||
std::unique_ptr<Screen> current;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
30
src/displayapp/screens/Symbols.h
Normal file
30
src/displayapp/screens/Symbols.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
namespace Symbols {
|
||||
static constexpr const char* none = "";
|
||||
static constexpr const char* batteryFull = "\xEF\x89\x80";
|
||||
static constexpr const char* batteryEmpty = "\xEF\x89\x84";
|
||||
static constexpr const char* batteryThreeQuarter = "\xEF\x89\x81";
|
||||
static constexpr const char* batteryHalf = "\xEF\x89\x82";
|
||||
static constexpr const char* batteryOneQuarter = "\xEF\x89\x83";
|
||||
static constexpr const char* heartBeat = "\xEF\x88\x9E";
|
||||
static constexpr const char* bluetoothFull = "\xEF\x8A\x93";
|
||||
static constexpr const char* bluetooth = "\xEF\x8A\x94";
|
||||
static constexpr const char* plug = "\xEF\x87\xA6";
|
||||
static constexpr const char* shoe = "\xEF\x95\x8B";
|
||||
static constexpr const char* clock = "\xEF\x80\x97";
|
||||
static constexpr const char* info = "\xEF\x84\xA9";
|
||||
static constexpr const char* list = "\xEF\x80\xBA";
|
||||
static constexpr const char* sun = "\xEF\x86\x85";
|
||||
static constexpr const char* check = "\xEF\x95\xA0";
|
||||
static constexpr const char* music = "\xEF\x80\x81";
|
||||
static constexpr const char* tachometer = "\xEF\x8F\xBD";
|
||||
static constexpr const char* asterisk = "\xEF\x81\xA9";
|
||||
static constexpr const char* paintbrush = "\xEF\x87\xBC";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
116
src/displayapp/screens/SystemInfo.cpp
Normal file
116
src/displayapp/screens/SystemInfo.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <DisplayApp/DisplayApp.h>
|
||||
#include <functional>
|
||||
#include "SystemInfo.h"
|
||||
#include "../../Version.h"
|
||||
#include "Tile.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp *app,
|
||||
Pinetime::Controllers::DateTime &dateTimeController,
|
||||
Pinetime::Controllers::Battery& batteryController,
|
||||
Pinetime::Controllers::BrightnessController& brightnessController,
|
||||
Pinetime::Controllers::Ble& bleController,
|
||||
Pinetime::Drivers::WatchdogView& watchdog) :
|
||||
Screen(app),
|
||||
dateTimeController{dateTimeController}, batteryController{batteryController},
|
||||
brightnessController{brightnessController}, bleController{bleController}, watchdog{watchdog},
|
||||
screens{app, {
|
||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen1(); },
|
||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen2(); },
|
||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); }
|
||||
}
|
||||
} {}
|
||||
|
||||
|
||||
SystemInfo::~SystemInfo() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool SystemInfo::Refresh() {
|
||||
screens.Refresh();
|
||||
return running;
|
||||
}
|
||||
|
||||
bool SystemInfo::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SystemInfo::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
return screens.OnTouchEvent(event);
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> SystemInfo::CreateScreen1() {
|
||||
auto batteryPercentF = batteryController.PercentRemaining();
|
||||
uint16_t batteryPercent = 0;
|
||||
if(batteryPercentF > 100.0f) batteryPercent = 100;
|
||||
else if(batteryPercentF < 0.0f) batteryPercent = 0;
|
||||
|
||||
uint8_t brightness = 0;
|
||||
switch(brightnessController.Level()) {
|
||||
case Controllers::BrightnessController::Levels::Off: brightness = 0; break;
|
||||
case Controllers::BrightnessController::Levels::Low: brightness = 1; break;
|
||||
case Controllers::BrightnessController::Levels::Medium: brightness = 2; break;
|
||||
case Controllers::BrightnessController::Levels::High: brightness = 3; break;
|
||||
}
|
||||
auto resetReason = [this]() {
|
||||
switch (watchdog.ResetReason()) {
|
||||
case Drivers::Watchdog::ResetReasons::Watchdog: return "wtdg";
|
||||
case Drivers::Watchdog::ResetReasons::HardReset: return "hardr";
|
||||
case Drivers::Watchdog::ResetReasons::NFC: return "nfc";
|
||||
case Drivers::Watchdog::ResetReasons::SoftReset: return "softr";
|
||||
case Drivers::Watchdog::ResetReasons::CpuLockup: return "cpulock";
|
||||
case Drivers::Watchdog::ResetReasons::SystemOff: return "off";
|
||||
case Drivers::Watchdog::ResetReasons::LpComp: return "lpcomp";
|
||||
case Drivers::Watchdog::ResetReasons::DebugInterface: return "dbg";
|
||||
case Drivers::Watchdog::ResetReasons::ResetPin: return "rst";
|
||||
default: return "?";
|
||||
}
|
||||
}();
|
||||
|
||||
// uptime
|
||||
static constexpr uint32_t secondsInADay = 60*60*24;
|
||||
static constexpr uint32_t secondsInAnHour = 60*60;
|
||||
static constexpr uint32_t secondsInAMinute = 60;
|
||||
uint32_t uptimeSeconds = dateTimeController.Uptime().count();
|
||||
uint32_t uptimeDays = (uptimeSeconds / secondsInADay);
|
||||
uptimeSeconds = uptimeSeconds % secondsInADay;
|
||||
uint32_t uptimeHours = uptimeSeconds / secondsInAnHour;
|
||||
uptimeSeconds = uptimeSeconds % secondsInAnHour;
|
||||
uint32_t uptimeMinutes = uptimeSeconds / secondsInAMinute;
|
||||
uptimeSeconds = uptimeSeconds % secondsInAMinute;
|
||||
// TODO handle more than 100 days of uptime
|
||||
|
||||
sprintf(t1, "Pinetime\n"
|
||||
"Version:%ld.%ld.%ld\n"
|
||||
"Build: %s\n"
|
||||
" %s\n"
|
||||
"Date: %02d/%02d/%04d\n"
|
||||
"Time: %02d:%02d:%02d\n"
|
||||
"Uptime: %02lud %02lu:%02lu:%02lu\n"
|
||||
"Battery: %d%%\n"
|
||||
"Backlight: %d/3\n"
|
||||
"Last reset: %s\n",
|
||||
Version::Major(), Version::Minor(), Version::Patch(),
|
||||
__DATE__, __TIME__,
|
||||
dateTimeController.Day(), static_cast<uint8_t>(dateTimeController.Month()), dateTimeController.Year(),
|
||||
dateTimeController.Hours(), dateTimeController.Minutes(), dateTimeController.Seconds(),
|
||||
uptimeDays, uptimeHours, uptimeMinutes, uptimeSeconds,
|
||||
batteryPercent, brightness, resetReason);
|
||||
|
||||
return std::unique_ptr<Screen>(new Screens::Label(app, t1));
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
||||
auto& bleAddr = bleController.Address();
|
||||
sprintf(t2, "BLE MAC: \n %2x:%2x:%2x:%2x:%2x:%2x",
|
||||
bleAddr[5], bleAddr[4], bleAddr[3], bleAddr[2], bleAddr[1], bleAddr[0]);
|
||||
return std::unique_ptr<Screen>(new Screens::Label(app, t2));
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> SystemInfo::CreateScreen3() {
|
||||
strncpy(t3, "Hello from\nthe developper!", 27);
|
||||
return std::unique_ptr<Screen>(new Screens::Label(app, t3));
|
||||
}
|
47
src/displayapp/screens/SystemInfo.h
Normal file
47
src/displayapp/screens/SystemInfo.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <Components/Ble/NimbleController.h>
|
||||
#include "Screen.h"
|
||||
#include "Label.h"
|
||||
#include "ScreenList.h"
|
||||
#include "Gauge.h"
|
||||
#include "Meter.h"
|
||||
#include <functional>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class SystemInfo : public Screen {
|
||||
public:
|
||||
explicit SystemInfo(DisplayApp* app,
|
||||
Pinetime::Controllers::DateTime& dateTimeController,
|
||||
Pinetime::Controllers::Battery& batteryController,
|
||||
Pinetime::Controllers::BrightnessController& brightnessController,
|
||||
Pinetime::Controllers::Ble& bleController,
|
||||
Pinetime::Drivers::WatchdogView& watchdog);
|
||||
~SystemInfo() override;
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
private:
|
||||
bool running = true;
|
||||
|
||||
Pinetime::Controllers::DateTime& dateTimeController;
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
Pinetime::Controllers::BrightnessController& brightnessController;
|
||||
Pinetime::Controllers::Ble& bleController;
|
||||
Pinetime::Drivers::WatchdogView& watchdog;
|
||||
|
||||
char t1[200];
|
||||
char t2[200];
|
||||
char t3[30];
|
||||
|
||||
ScreenList<3> screens;
|
||||
std::unique_ptr<Screen> CreateScreen1();
|
||||
std::unique_ptr<Screen> CreateScreen2();
|
||||
std::unique_ptr<Screen> CreateScreen3();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
67
src/displayapp/screens/Tab.cpp
Normal file
67
src/displayapp/screens/Tab.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <cstdio>
|
||||
#include <libs/date/includes/date/date.h>
|
||||
#include <Components/DateTime/DateTimeController.h>
|
||||
#include <Version.h>
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <libs/lvgl/src/lv_font/lv_font.h>
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <libraries/log/nrf_log.h>
|
||||
#include "Tab.h"
|
||||
#include <DisplayApp/DisplayApp.h>
|
||||
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
//static void event_handler(lv_obj_t * obj, lv_event_t event) {
|
||||
// Tile* screen = static_cast<Tile *>(obj->user_data);
|
||||
// screen->OnObjectEvent(obj, event);
|
||||
//}
|
||||
|
||||
Tab::Tab(DisplayApp* app, Pinetime::Components::Gfx &gfx) : Screen(app, gfx) {
|
||||
/*Create a Tab view object*/
|
||||
lv_obj_t *tabview;
|
||||
tabview = lv_tabview_create(lv_scr_act(), NULL);
|
||||
|
||||
/*Add 3 tabs (the tabs are page (lv_page) and can be scrolled*/
|
||||
lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Tab 1");
|
||||
lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Tab 2");
|
||||
lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Tab 3");
|
||||
|
||||
|
||||
/*Add content to the tabs*/
|
||||
lv_obj_t * label = lv_label_create(tab1, NULL);
|
||||
lv_label_set_text(label, "This the first tab\n\n"
|
||||
"If the content\n"
|
||||
"of a tab\n"
|
||||
"become too long\n"
|
||||
"the it \n"
|
||||
"automatically\n"
|
||||
"become\n"
|
||||
"scrollable.");
|
||||
|
||||
label = lv_label_create(tab2, NULL);
|
||||
lv_label_set_text(label, "Second tab");
|
||||
|
||||
label = lv_label_create(tab3, NULL);
|
||||
lv_label_set_text(label, "Third tab");
|
||||
|
||||
}
|
||||
|
||||
Tab::~Tab() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
void Tab::Refresh(bool fullRefresh) {
|
||||
|
||||
}
|
||||
|
||||
void Tab::OnObjectEvent(lv_obj_t *obj, lv_event_t event) {
|
||||
if(event == LV_EVENT_CLICKED) {
|
||||
NRF_LOG_INFO("Clicked");
|
||||
}
|
||||
else if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
NRF_LOG_INFO("Toggled");
|
||||
}
|
||||
}
|
23
src/displayapp/screens/Tab.h
Normal file
23
src/displayapp/screens/Tab.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include <lvgl/src/lv_core/lv_style.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class Tab : public Screen {
|
||||
public:
|
||||
explicit Tab(DisplayApp* app, Components::Gfx& gfx);
|
||||
~Tab() override;
|
||||
void Refresh(bool fullRefresh) override;
|
||||
void OnObjectEvent(lv_obj_t* obj, lv_event_t event);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
61
src/displayapp/screens/Tile.cpp
Normal file
61
src/displayapp/screens/Tile.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <libs/lvgl/src/lv_core/lv_obj.h>
|
||||
#include <libs/lvgl/src/lv_font/lv_font.h>
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include "Tile.h"
|
||||
#include <DisplayApp/DisplayApp.h>
|
||||
#include "Symbols.h"
|
||||
#include "../../Version.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
extern lv_font_t jetbrains_mono_bold_20;
|
||||
|
||||
static void event_handler(lv_obj_t * obj, lv_event_t event) {
|
||||
Tile* screen = static_cast<Tile *>(obj->user_data);
|
||||
uint32_t* eventDataPtr = (uint32_t*) lv_event_get_data();
|
||||
uint32_t eventData = *eventDataPtr;
|
||||
screen->OnObjectEvent(obj, event, eventData);
|
||||
}
|
||||
|
||||
Tile::Tile(DisplayApp* app, std::array<Applications, 6>& applications) : Screen(app) {
|
||||
for(int i = 0, appIndex = 0; i < 8; i++) {
|
||||
if(i == 3) btnm_map1[i] = "\n";
|
||||
else if(i == 7) btnm_map1[i] = "";
|
||||
else {
|
||||
btnm_map1[i] = applications[appIndex].icon;
|
||||
apps[appIndex] = applications[appIndex].application;
|
||||
appIndex++;
|
||||
}
|
||||
}
|
||||
modal.reset(new Modal(app));
|
||||
|
||||
btnm1 = lv_btnm_create(lv_scr_act(), NULL);
|
||||
lv_btnm_set_map(btnm1, btnm_map1);
|
||||
lv_obj_set_size(btnm1, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
btnm1->user_data = this;
|
||||
lv_obj_set_event_cb(btnm1, event_handler);
|
||||
}
|
||||
|
||||
Tile::~Tile() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool Tile::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
||||
void Tile::OnObjectEvent(lv_obj_t *obj, lv_event_t event, uint32_t buttonId) {
|
||||
if(event == LV_EVENT_VALUE_CHANGED) {
|
||||
app->StartApp(apps[buttonId]);
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Tile::OnButtonPushed() {
|
||||
app->StartApp(Apps::Clock);
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
39
src/displayapp/screens/Tile.h
Normal file
39
src/displayapp/screens/Tile.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "Screen.h"
|
||||
#include <bits/unique_ptr.h>
|
||||
#include "Modal.h"
|
||||
#include <lvgl/src/lv_core/lv_style.h>
|
||||
#include <DisplayApp/Apps.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class Tile : public Screen {
|
||||
public:
|
||||
struct Applications {
|
||||
const char* icon;
|
||||
Pinetime::Applications::Apps application;
|
||||
};
|
||||
|
||||
explicit Tile(DisplayApp* app, std::array<Applications, 6>& applications);
|
||||
~Tile() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
void OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId);
|
||||
|
||||
private:
|
||||
lv_obj_t * btnm1;
|
||||
bool running = true;
|
||||
|
||||
std::unique_ptr<Modal> modal;
|
||||
|
||||
const char* btnm_map1[8];
|
||||
Pinetime::Applications::Apps apps[6];
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user