Port to C++
This commit is contained in:
parent
c19b3b776f
commit
b6aadd4601
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
build/
|
||||
compile_commands.json
|
||||
|
2
Makefile
2
Makefile
@ -25,7 +25,7 @@ OFILES := $(addprefix $(OFILE_DIR)/, $(notdir $(C_SOURCES:.c=.o) $(CXX_SOUR
|
||||
OPT := -O2
|
||||
CPPFLAGS := $(INCLUDES) -MMD
|
||||
CFLAGS := $(OPT) -Wall -Wextra -Wpedantic
|
||||
CXXFLAGS := $(OPT) -std=c++17 -Wall -Wextra -Wpedantic
|
||||
CXXFLAGS := $(OPT) -std=c++17 -Wall -Wextra #-Wpedantic
|
||||
|
||||
|
||||
LDFLAGS :=
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,23 +7,7 @@
|
||||
#define MAX_DAYS_IN_MONTH 31
|
||||
|
||||
|
||||
typedef enum {
|
||||
JANUARY = 0,
|
||||
FEBRUARY,
|
||||
MARCH,
|
||||
APRIL,
|
||||
MAY,
|
||||
JUNE,
|
||||
JULY,
|
||||
AUGUST,
|
||||
SEPTEMBER,
|
||||
OCTOBER,
|
||||
NOVEMBER,
|
||||
DECEMBER,
|
||||
} MONTH;
|
||||
|
||||
|
||||
bool isLeapYear(int year);
|
||||
uint8_t firstDayOfMonth(MONTH month, int year);
|
||||
uint8_t daysInMonth(MONTH month, int year);
|
||||
uint8_t firstDayOfMonth(int month, int year);
|
||||
uint8_t daysInMonth(int month, int year);
|
||||
|
||||
|
31
inc/events.h
31
inc/events.h
@ -11,16 +11,19 @@
|
||||
#define STR_MAX_NAME_LEN "99"
|
||||
|
||||
|
||||
typedef enum {
|
||||
namespace Events {
|
||||
|
||||
|
||||
enum EVENT_TYPE {
|
||||
EVENTS_MEETING = 0,
|
||||
EVENTS_CASCADE,
|
||||
EVENTS_SETUP,
|
||||
EVENTS_APPOINTMENT,
|
||||
EVENTS_OTHER,
|
||||
EVENTS_COUNT,
|
||||
} EVENT_TYPE;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct event_type_counts {
|
||||
uint8_t counts[EVENTS_COUNT];
|
||||
// uint8_t other;
|
||||
// uint8_t meetings;
|
||||
@ -28,27 +31,23 @@ typedef struct {
|
||||
// uint8_t cascades;
|
||||
// uint8_t setups;
|
||||
// uint8_t appointments
|
||||
} event_type_counts_t;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct Event {
|
||||
int s_hour;
|
||||
int s_min;
|
||||
int e_hour;
|
||||
int e_min;
|
||||
EVENT_TYPE type;
|
||||
char name[MAX_NAME_LEN];
|
||||
} event_t;
|
||||
|
||||
typedef struct {
|
||||
event_t* events;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
} events_t;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void unregisterAllUpdates(void);
|
||||
void registerUpdateOnEventChange(uint8_t day, lv_obj_t* object);
|
||||
void register_update_on_detailed_events_change(lv_obj_t* object);
|
||||
void updateEvents(uint8_t today, MONTH month, uint32_t year);
|
||||
void unregisterCallbacks(void);
|
||||
void registerCallback(uint8_t day, lv_obj_t* object);
|
||||
void registerDetailedCallback(lv_obj_t* object);
|
||||
void update(uint8_t today, int month, uint32_t year);
|
||||
|
||||
} // namespace Events
|
||||
|
||||
|
@ -12,8 +12,7 @@ struct framebuf {
|
||||
uint16_t* buf;
|
||||
};
|
||||
|
||||
int open_fb(struct framebuf* fb, const char* const dev);
|
||||
void close_fb(struct framebuf* fb);
|
||||
void clear_fb(struct framebuf* fb);
|
||||
void set_pixel(struct framebuf* fb, uint32_t x, uint32_t y, uint16_t color);
|
||||
int open_fb(framebuf* fb, const char* const dev);
|
||||
void close_fb(framebuf* fb);
|
||||
void clear_fb(framebuf* fb);
|
||||
|
||||
|
@ -5,10 +5,6 @@
|
||||
#include <lvgl.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t disp_height;
|
||||
extern uint32_t disp_width;
|
||||
|
||||
@ -18,7 +14,3 @@ uint32_t disp_hpercent_to_px(uint32_t percent);
|
||||
uint32_t disp_vpercent_to_px(uint32_t percent);
|
||||
int lvgl_fb_run(const char* const fb_dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
@ -11,30 +12,55 @@
|
||||
#define CALENDAR_ROWS 5
|
||||
|
||||
|
||||
typedef struct lvc_calendar_box {
|
||||
struct CalendarBox {
|
||||
public:
|
||||
CalendarBox(lv_obj_t* parent);
|
||||
~CalendarBox();
|
||||
|
||||
void Style(uint32_t width, uint32_t height, int day, int wday, bool today, int days_in_month);
|
||||
|
||||
public:
|
||||
lv_obj_t* box;
|
||||
|
||||
private:
|
||||
static void DrawEvents_cb(lv_event_t* event);
|
||||
|
||||
private:
|
||||
lv_obj_t* label;
|
||||
|
||||
lv_obj_t* event_count_labels[EVENTS_COUNT];
|
||||
} lvc_calendar_box_t;
|
||||
lv_obj_t* event_count_labels[Events::EVENTS_COUNT];
|
||||
};
|
||||
|
||||
typedef struct lvc_calendar_row {
|
||||
lvc_calendar_box_t* boxes[DAYS_IN_WEEK];
|
||||
} lvc_calendar_row_t;
|
||||
|
||||
typedef struct lvc_calendar {
|
||||
struct CalendarRow {
|
||||
public:
|
||||
CalendarRow(lv_obj_t* parent);
|
||||
~CalendarRow();
|
||||
|
||||
int Style(lv_obj_t* last_row, uint32_t box_width, uint32_t box_height, int day, int current_day, int days_in_month);
|
||||
|
||||
public:
|
||||
CalendarBox* boxes[DAYS_IN_WEEK];
|
||||
};
|
||||
|
||||
|
||||
class Calendar {
|
||||
public:
|
||||
Calendar(lv_obj_t* parent, uint32_t width);
|
||||
~Calendar();
|
||||
|
||||
void Style(const struct tm* const ct);
|
||||
|
||||
public:
|
||||
lv_obj_t* calendar;
|
||||
|
||||
private:
|
||||
lv_obj_t* title_bar;
|
||||
lv_obj_t* title_label;
|
||||
lvc_calendar_row_t* rows[CALENDAR_ROWS];
|
||||
CalendarRow* rows[CALENDAR_ROWS];
|
||||
|
||||
uint32_t width;
|
||||
uint32_t box_width;
|
||||
uint32_t box_height;
|
||||
};
|
||||
|
||||
} lvc_calendar_t;
|
||||
|
||||
|
||||
|
||||
lvc_calendar_t* create_calendar(lv_obj_t* parent, uint32_t width);
|
||||
void destroy_calendar(lvc_calendar_t* cal);
|
||||
|
@ -1,13 +1,21 @@
|
||||
#include <lvgl.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef struct {
|
||||
class EventsPanel {
|
||||
public:
|
||||
EventsPanel(lv_obj_t* parent);
|
||||
~EventsPanel();
|
||||
void Style();
|
||||
|
||||
public:
|
||||
lv_obj_t* panel;
|
||||
|
||||
private:
|
||||
static void DrawEventList_cb(lv_event_t* event);
|
||||
|
||||
private:
|
||||
lv_obj_t* header;
|
||||
lv_obj_t** event_labels;
|
||||
uint16_t event_labels_count;
|
||||
} lvc_events_panel_t;
|
||||
std::vector<lv_obj_t*> event_labels;
|
||||
};
|
||||
|
||||
|
||||
lvc_events_panel_t* create_events_panel(lv_obj_t* parent);
|
||||
void destroy_events_panel(lvc_events_panel_t* panel);
|
||||
|
@ -18,7 +18,7 @@ bool isLeapYear(int year)
|
||||
return (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
|
||||
uint8_t firstDayOfMonth(MONTH month, int year)
|
||||
uint8_t firstDayOfMonth(int month, int year)
|
||||
{
|
||||
int d = year % 100;
|
||||
uint8_t first_of_year = (century_start[(year / 100) % 4] + d + (d / 4) - isLeapYear(year) + 7) % 7;
|
||||
@ -29,7 +29,7 @@ uint8_t firstDayOfMonth(MONTH month, int year)
|
||||
return (first_of_year + offsets[month]) % 7;
|
||||
}
|
||||
|
||||
uint8_t daysInMonth(MONTH month, int year)
|
||||
uint8_t daysInMonth(int month, int year)
|
||||
{
|
||||
if (isLeapYear(year))
|
||||
{
|
@ -1,4 +1,5 @@
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -12,29 +13,29 @@
|
||||
#include "events.h"
|
||||
|
||||
|
||||
#define MAX_FILE_NAME_LEN 36
|
||||
#define MAX_FILE_NAME_LEN 42
|
||||
#define MAX_LINE_LEN 200
|
||||
#define FILE_PATH_FMT "/var/lib/calzone/%02d_%d.csv"
|
||||
#define FILE_LINE_FMT "%d,%d,%d,%d,%d,%u,%" STR_MAX_NAME_LEN "[^\t\n]"
|
||||
#define FILE_LINE_FMT_QUOTE "%d,%d,%d,%d,%d,%u,\"%" STR_MAX_NAME_LEN "[^\t\n\"]\""
|
||||
|
||||
|
||||
namespace Events {
|
||||
|
||||
static time_t modified_time = 0;
|
||||
static event_type_counts_t event_counts[MAX_DAYS_IN_MONTH];
|
||||
static event_type_counts event_counts[MAX_DAYS_IN_MONTH];
|
||||
static lv_obj_t* objects_to_update[MAX_DAYS_IN_MONTH];
|
||||
static lv_obj_t* detailed_events_object = NULL;
|
||||
static events_t event_array;
|
||||
static lv_obj_t* detailed_events_object = nullptr;
|
||||
static std::vector<Event> events;
|
||||
|
||||
|
||||
void clearEvents(void);
|
||||
void sendEventsToObjects(void);
|
||||
void dispatchCallbacks(void);
|
||||
bool wasModified(const char* const file_name);
|
||||
int readEventsFromFile(const char* const file_name, int today);
|
||||
int addEvent(event_t* event);
|
||||
|
||||
|
||||
void registerUpdateOnEventChange(uint8_t day, lv_obj_t* object)
|
||||
void registerCallback(uint8_t day, lv_obj_t* object)
|
||||
{
|
||||
day -= 1;
|
||||
if (day >= MAX_DAYS_IN_MONTH) {
|
||||
@ -44,19 +45,19 @@ void registerUpdateOnEventChange(uint8_t day, lv_obj_t* object)
|
||||
objects_to_update[day] = object;
|
||||
}
|
||||
|
||||
void register_update_on_detailed_events_change(lv_obj_t* object)
|
||||
void registerDetailedCallback(lv_obj_t* object)
|
||||
{
|
||||
detailed_events_object = object;
|
||||
}
|
||||
|
||||
void unregisterAllUpdates(void)
|
||||
void unregisterCallbacks(void)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_DAYS_IN_MONTH; i++) {
|
||||
objects_to_update[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void updateEvents(uint8_t today, MONTH month, uint32_t year)
|
||||
void update(uint8_t today, int month, uint32_t year)
|
||||
{
|
||||
// No real reason to have the limit at year 100 000 000 since the pi zero's time will die in 2038,
|
||||
// but I just pushed nine a bunch of times and now this is how it is
|
||||
@ -70,28 +71,28 @@ void updateEvents(uint8_t today, MONTH month, uint32_t year)
|
||||
// Check if file exists
|
||||
if (access(file_name, F_OK) != 0) {
|
||||
clearEvents();
|
||||
sendEventsToObjects();
|
||||
dispatchCallbacks();
|
||||
return;
|
||||
}
|
||||
|
||||
if (wasModified(file_name)) {
|
||||
clearEvents();
|
||||
if (readEventsFromFile(file_name, today) != 0) {
|
||||
sendEventsToObjects();
|
||||
dispatchCallbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendEventsToObjects(void)
|
||||
void dispatchCallbacks(void)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_DAYS_IN_MONTH; i++) {
|
||||
if (objects_to_update[i] != NULL) {
|
||||
if (objects_to_update[i] != nullptr) {
|
||||
lv_obj_send_event(objects_to_update[i], LV_EVENT_REFRESH, &event_counts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (detailed_events_object != NULL) {
|
||||
lv_obj_send_event(detailed_events_object, LV_EVENT_REFRESH, &event_array);
|
||||
if (detailed_events_object != nullptr) {
|
||||
lv_obj_send_event(detailed_events_object, LV_EVENT_REFRESH, &events);
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +110,7 @@ bool wasModified(const char* const file_name)
|
||||
|
||||
void clearEvents(void)
|
||||
{
|
||||
event_array.size = 0;
|
||||
events.clear();
|
||||
modified_time = 0;
|
||||
|
||||
for (size_t i = 0; i < MAX_DAYS_IN_MONTH; i++) {
|
||||
@ -122,7 +123,7 @@ void clearEvents(void)
|
||||
int readEventsFromFile(const char* const file_name, int today)
|
||||
{
|
||||
FILE* f = fopen(file_name, "r");
|
||||
if (f == NULL) {
|
||||
if (f == nullptr) {
|
||||
printf("Failed to acces file %s\n", file_name);
|
||||
return 0;
|
||||
}
|
||||
@ -132,11 +133,11 @@ int readEventsFromFile(const char* const file_name, int today)
|
||||
|
||||
int day;
|
||||
int num_events = 0;
|
||||
event_t event;
|
||||
Event event;
|
||||
|
||||
while (1) {
|
||||
char* b = fgets(buf, MAX_LINE_LEN, f);
|
||||
if (b == NULL) {
|
||||
if (b == nullptr) {
|
||||
// Error or EOF
|
||||
break;
|
||||
}
|
||||
@ -146,11 +147,12 @@ int readEventsFromFile(const char* const file_name, int today)
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int event_type_int;
|
||||
int num = sscanf(buf, FILE_LINE_FMT_QUOTE,
|
||||
&event.s_hour, &event.s_min, &event.e_hour, &event.e_min, &day, &event.type, event.name);
|
||||
&event.s_hour, &event.s_min, &event.e_hour, &event.e_min, &day, &event_type_int, event.name);
|
||||
if (num != 7) {
|
||||
num = sscanf(buf, FILE_LINE_FMT,
|
||||
&event.s_hour, &event.s_min, &event.e_hour, &event.e_min, &day, &event.type, event.name);
|
||||
&event.s_hour, &event.s_min, &event.e_hour, &event.e_min, &day, &event_type_int, event.name);
|
||||
if (num != 7) {
|
||||
printf("Malformed line in events list file\n");
|
||||
continue;
|
||||
@ -161,12 +163,13 @@ int readEventsFromFile(const char* const file_name, int today)
|
||||
printf("Invalid day %d\n", day);
|
||||
}
|
||||
|
||||
event.type = static_cast<EVENT_TYPE>(event_type_int);
|
||||
if (event.type >= EVENTS_COUNT) {
|
||||
event.type = EVENTS_OTHER;
|
||||
}
|
||||
|
||||
if (day == today) {
|
||||
addEvent(&event);
|
||||
events.push_back(event);
|
||||
}
|
||||
|
||||
event_counts[day - 1].counts[event.type] += 1;
|
||||
@ -178,20 +181,5 @@ int readEventsFromFile(const char* const file_name, int today)
|
||||
return num_events;
|
||||
}
|
||||
|
||||
int addEvent(event_t* event)
|
||||
{
|
||||
if (event_array.size + 1 > event_array.capacity) {
|
||||
size_t newCapacity = event_array.capacity < 2 ? 4 : event_array.capacity * 2;
|
||||
event_t* newMem = reallocarray(event_array.events, newCapacity, sizeof(event_t));
|
||||
if (newMem == NULL) {
|
||||
printf("Call to reallocarray failed. Unable to load more event_array");
|
||||
return -1;
|
||||
}
|
||||
event_array.events = newMem;
|
||||
event_array.capacity = newCapacity;
|
||||
}
|
||||
|
||||
memcpy(&event_array.events[event_array.size++], event, sizeof(event_t));
|
||||
return 0;
|
||||
}
|
||||
} // namespace Events
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "fbd.h"
|
||||
|
||||
int open_fb(struct framebuf* fb, const char* const dev)
|
||||
int open_fb(framebuf* fb, const char* const dev)
|
||||
{
|
||||
fb->fd = open(dev, O_RDWR);
|
||||
if (fb->fd < 0) {
|
||||
@ -16,17 +16,17 @@ int open_fb(struct framebuf* fb, const char* const dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// struct fb_fix_screeninfo fix_info;
|
||||
// fb_fix_screeninfo fix_info;
|
||||
// ioctl(fd, FBIOGET_FSCREENINFO, &fix_info);
|
||||
|
||||
struct fb_var_screeninfo var_info;
|
||||
fb_var_screeninfo var_info;
|
||||
ioctl(fb->fd, FBIOGET_VSCREENINFO, &var_info);
|
||||
|
||||
fb->xres = var_info.xres;
|
||||
fb->yres = var_info.yres;
|
||||
fb->size = fb->xres * fb->yres * (var_info.bits_per_pixel / 8);
|
||||
|
||||
fb->buf = mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
|
||||
fb->buf = (uint16_t*) mmap(0, fb->size, PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
|
||||
if (fb->buf == MAP_FAILED) {
|
||||
printf("Failed to map framebuf\n");
|
||||
return -2;
|
||||
@ -35,7 +35,7 @@ int open_fb(struct framebuf* fb, const char* const dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_fb(struct framebuf* fb)
|
||||
void close_fb(framebuf* fb)
|
||||
{
|
||||
// memset(fb->buf, 0, fb->size);
|
||||
munmap(fb->buf, fb->size);
|
||||
@ -48,14 +48,8 @@ void close_fb(struct framebuf* fb)
|
||||
fb->fd = -1;
|
||||
}
|
||||
|
||||
void clear_fb(struct framebuf* fb)
|
||||
void clear_fb(framebuf* fb)
|
||||
{
|
||||
memset(fb->buf, 0, fb->size);
|
||||
}
|
||||
|
||||
void set_pixel(struct framebuf* fb, uint32_t x, uint32_t y, uint16_t color)
|
||||
{
|
||||
uint32_t idx = (y * fb->xres) + x;
|
||||
|
||||
fb->buf[idx] = color;
|
||||
}
|
@ -27,7 +27,7 @@ void* tick_thread(void* arg);
|
||||
|
||||
void fb_flush_cb(lv_display_t* display, const lv_area_t* area, uint8_t* px_map)
|
||||
{
|
||||
struct framebuf* fb = (struct framebuf*)lv_display_get_user_data(display);
|
||||
framebuf* fb = (framebuf*)lv_display_get_user_data(display);
|
||||
|
||||
int32_t area_width_b = (area->x2 - area->x1 + 1) * 2; // Two bytes per pixel
|
||||
|
||||
@ -58,7 +58,7 @@ int lvgl_fb_run(const char* const fb_dev)
|
||||
sigaction(SIGINT, &act, NULL);
|
||||
|
||||
|
||||
struct framebuf fb;
|
||||
framebuf fb;
|
||||
int ret = open_fb(&fb, fb_dev);
|
||||
if (ret != 0) {
|
||||
printf("Failed to open framebuf. Error: %d\n", ret);
|
||||
@ -78,7 +78,7 @@ int lvgl_fb_run(const char* const fb_dev)
|
||||
lv_display_set_flush_cb(display, fb_flush_cb);
|
||||
lv_display_set_user_data(display, &fb);
|
||||
|
||||
uint16_t* buf1 = (uint16_t*)malloc(fb.size);
|
||||
uint16_t* buf1 = new uint16_t[fb.size];
|
||||
lv_display_set_buffers(display, buf1, NULL, fb.size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ int lvgl_fb_run(const char* const fb_dev)
|
||||
|
||||
// Copied from https://stackoverflow.com/a/27558789
|
||||
pthread_attr_t attr;
|
||||
struct sched_param param;
|
||||
sched_param param;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_getschedparam(&attr, ¶m);
|
@ -1,279 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
#include "date_utils.h"
|
||||
#include "calendar.h"
|
||||
#include "fonts.h"
|
||||
|
||||
|
||||
static lv_style_t box_style;
|
||||
static lv_style_t box_style_active;
|
||||
static lv_style_t box_style_inactive;
|
||||
|
||||
static const char* const month_list[] = {
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
};
|
||||
|
||||
static const char* const event_format_strs[] = {
|
||||
NF_SYMBOL_CAMERA " %d meeting(s)",
|
||||
NF_SYMBOL_UPDATE " %d cascade(s)",
|
||||
NF_SYMBOL_LAPTOP " %d setup(s)",
|
||||
NF_SYMBOL_CALENDAR " %d appointment(s)",
|
||||
NF_SYMBOL_CALENDAR_QUESTION " %d other event(s)",
|
||||
};
|
||||
|
||||
|
||||
lvc_calendar_row_t* create_row(lv_obj_t* parent);
|
||||
lvc_calendar_box_t* create_box(lv_obj_t* parent);
|
||||
void destroy_row(lvc_calendar_row_t* row);
|
||||
void destroy_box(lvc_calendar_box_t* row);
|
||||
void style_calendar(lvc_calendar_t* cal, const struct tm* const ct);
|
||||
int style_row(lvc_calendar_row_t* row, lv_obj_t* last_row, uint32_t box_width, uint32_t box_height, int day, int current_day, int days_in_month);
|
||||
void style_box(lvc_calendar_box_t* box, uint32_t width, uint32_t height, int day, int wday, bool today, int days_in_month);
|
||||
void draw_event_list_cb(lv_event_t* event);
|
||||
void calendar_refresh_event(lv_event_t* event);
|
||||
|
||||
|
||||
|
||||
static inline void init_style(uint32_t box_width, uint32_t box_height)
|
||||
{
|
||||
lv_style_init(&box_style);
|
||||
lv_style_set_width(&box_style, box_width);
|
||||
lv_style_set_height(&box_style, box_height);
|
||||
lv_style_set_radius(&box_style, 0);
|
||||
lv_style_set_bg_color(&box_style, lv_color_hex(0xffffff));
|
||||
lv_style_set_bg_opa(&box_style, LV_OPA_COVER);
|
||||
lv_style_set_border_width(&box_style, 2);
|
||||
lv_style_set_border_color(&box_style, lv_color_hex(0x333333));
|
||||
lv_style_set_pad_all(&box_style, 5);
|
||||
|
||||
lv_style_init(&box_style_active);
|
||||
lv_style_set_bg_color(&box_style_active, lv_color_hex(0xbbbbbb));
|
||||
lv_style_set_text_color(&box_style_active, lv_color_hex(0x000000));
|
||||
|
||||
lv_style_init(&box_style_inactive);
|
||||
lv_style_set_bg_color(&box_style_inactive, lv_color_hex(0x646464));
|
||||
}
|
||||
|
||||
lvc_calendar_t* create_calendar(lv_obj_t* parent, uint32_t width)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
struct tm* ct = localtime(&t);
|
||||
|
||||
lvc_calendar_t* cal = malloc(sizeof(lvc_calendar_t));
|
||||
cal->calendar = lv_obj_create(parent);
|
||||
cal->title_bar = lv_obj_create(cal->calendar);
|
||||
cal->title_label = lv_label_create(cal->title_bar);
|
||||
cal->width = width - (width % 7);
|
||||
cal->box_width = cal->width / 7;
|
||||
cal->box_height = cal->box_width * 0.8;
|
||||
|
||||
init_style(cal->box_width, cal->box_height);
|
||||
|
||||
for (uint8_t i = 0; i < CALENDAR_ROWS; i++) {
|
||||
cal->rows[i] = create_row(cal->calendar);
|
||||
}
|
||||
|
||||
style_calendar(cal, ct);
|
||||
|
||||
lv_obj_add_event_cb(cal->calendar, calendar_refresh_event, LV_EVENT_REFRESH, cal);
|
||||
|
||||
return cal;
|
||||
}
|
||||
|
||||
lvc_calendar_row_t* create_row(lv_obj_t* parent)
|
||||
{
|
||||
lvc_calendar_row_t* row = malloc(sizeof(lvc_calendar_row_t));
|
||||
|
||||
for (uint8_t i = 0; i < DAYS_IN_WEEK; i++) {
|
||||
row->boxes[i] = create_box(parent);
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
lvc_calendar_box_t* create_box(lv_obj_t* parent)
|
||||
{
|
||||
lvc_calendar_box_t* box = malloc(sizeof(lvc_calendar_box_t));
|
||||
|
||||
box->box = lv_obj_create(parent);
|
||||
box->label = lv_label_create(box->box);
|
||||
|
||||
for (size_t i = 0; i < EVENTS_COUNT; i++) {
|
||||
box->event_count_labels[i] = lv_label_create(box->box);
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
void destroy_calendar(lvc_calendar_t* cal)
|
||||
{
|
||||
for (uint8_t i = 0; i < CALENDAR_ROWS; i++) {
|
||||
destroy_row(cal->rows[i]);
|
||||
}
|
||||
|
||||
lv_obj_delete(cal->title_label);
|
||||
lv_obj_delete(cal->title_bar);
|
||||
lv_obj_delete(cal->calendar);
|
||||
|
||||
free(cal);
|
||||
}
|
||||
|
||||
void destroy_row(lvc_calendar_row_t* row)
|
||||
{
|
||||
for (uint8_t i = 0; i < DAYS_IN_WEEK; i++) {
|
||||
destroy_box(row->boxes[i]);
|
||||
}
|
||||
|
||||
free(row);
|
||||
}
|
||||
|
||||
void destroy_box(lvc_calendar_box_t* box)
|
||||
{
|
||||
lv_obj_delete(box->label);
|
||||
|
||||
for (size_t i = 0; i < EVENTS_COUNT; i++) {
|
||||
lv_obj_delete(box->event_count_labels[i]);
|
||||
}
|
||||
|
||||
lv_obj_delete(box->box);
|
||||
|
||||
free(box);
|
||||
}
|
||||
|
||||
void style_calendar(lvc_calendar_t* cal, const struct tm* const ct)
|
||||
{
|
||||
int days = daysInMonth(ct->tm_mon, ct->tm_year + 1900);
|
||||
int start_day = 1 - firstDayOfMonth(ct->tm_mon, ct->tm_year + 1900);
|
||||
|
||||
if (start_day == -5 && days == 31) {
|
||||
start_day += 7;
|
||||
}
|
||||
|
||||
lv_obj_set_size(cal->calendar, cal->width, cal->box_height * 6);
|
||||
lv_obj_set_style_pad_all(cal->calendar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(cal->calendar, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style_all(cal->title_bar);
|
||||
lv_obj_set_size(cal->title_bar, cal->width, cal->box_height);
|
||||
lv_obj_align(cal->title_bar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_pad_all(cal->title_bar, 0, LV_PART_MAIN);
|
||||
lv_obj_add_style(cal->title_bar, &box_style, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style_all(cal->title_label);
|
||||
lv_label_set_text_fmt(cal->title_label, "%s %d", month_list[ct->tm_mon], ct->tm_year + 1900);
|
||||
lv_obj_set_style_text_font(cal->title_label, &lv_font_montserrat_48, LV_PART_MAIN);
|
||||
lv_obj_center(cal->title_label);
|
||||
|
||||
unregisterAllUpdates();
|
||||
|
||||
lv_obj_t* last_row = cal->title_bar;
|
||||
for (uint8_t r = 0; r < CALENDAR_ROWS; r++) {
|
||||
start_day = style_row(cal->rows[r], last_row, cal->box_width, cal->box_height, start_day, ct->tm_mday, days);
|
||||
last_row = cal->rows[r]->boxes[0]->box;
|
||||
}
|
||||
|
||||
// Update events, so it will call our callbacks set in style_box to show the list of events
|
||||
updateEvents(ct->tm_mday, ct->tm_mon, ct->tm_year + 1900);
|
||||
}
|
||||
|
||||
int style_row(lvc_calendar_row_t* row, lv_obj_t* last_row, uint32_t box_width, uint32_t box_height, int day, int current_day, int days_in_month)
|
||||
{
|
||||
style_box(row->boxes[0], box_width, box_height, day, 0, day == current_day, days_in_month);
|
||||
lv_obj_align_to(row->boxes[0]->box, last_row, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
day++;
|
||||
|
||||
lv_obj_t* last = row->boxes[0]->box;
|
||||
for (uint8_t i = 1; i < DAYS_IN_WEEK; i++) {
|
||||
style_box(row->boxes[i], box_width, box_height, day, i, day == current_day, days_in_month);
|
||||
lv_obj_align_to(row->boxes[i]->box, last, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
|
||||
last = row->boxes[i]->box;
|
||||
day++;
|
||||
}
|
||||
|
||||
return day;
|
||||
}
|
||||
|
||||
void style_box(lvc_calendar_box_t* box, uint32_t width, uint32_t height, int day, int wday, bool today, int days_in_month)
|
||||
{
|
||||
lv_obj_remove_style_all(box->box);
|
||||
lv_obj_set_size(box->box, width, height);
|
||||
|
||||
lv_obj_add_style(box->box, &box_style, LV_PART_MAIN);
|
||||
if (today) {
|
||||
lv_obj_add_style(box->box, &box_style_active, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
if (wday == 6) {
|
||||
lv_obj_set_style_border_side(box->box, LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT, LV_PART_MAIN);
|
||||
} else {
|
||||
lv_obj_set_style_border_side(box->box, LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_LEFT, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
|
||||
lv_obj_align(box->label, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
if (day > 0 && day <= days_in_month) {
|
||||
lv_label_set_text_fmt(box->label, "%d", day);
|
||||
lv_obj_set_style_pad_bottom(box->label, 8, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(box->box, draw_event_list_cb, LV_EVENT_REFRESH, box);
|
||||
registerUpdateOnEventChange(day, box->box);
|
||||
} else {
|
||||
lv_obj_add_style(box->box, &box_style_inactive, LV_PART_MAIN);
|
||||
lv_label_set_text(box->label, "");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < EVENTS_COUNT; i++) {
|
||||
lv_label_set_text(box->event_count_labels[i], "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void draw_event_list_cb(lv_event_t* event)
|
||||
{
|
||||
event_type_counts_t* counts = lv_event_get_param(event);
|
||||
lvc_calendar_box_t* box = lv_event_get_user_data(event);
|
||||
|
||||
int c = 0;
|
||||
lv_obj_t* label = NULL;
|
||||
lv_obj_t* last = box->label;
|
||||
|
||||
for (size_t i = 0; i < EVENTS_COUNT; i++) {
|
||||
c = counts->counts[i];
|
||||
label = box->event_count_labels[i];
|
||||
|
||||
if (c != 0) {
|
||||
lv_label_set_text_fmt(label, event_format_strs[i], c);
|
||||
lv_obj_align_to(label, last, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_style_text_font(label, &nerdfonts_arimo_14, LV_PART_MAIN);
|
||||
last = label;
|
||||
} else {
|
||||
lv_label_set_text(label, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void calendar_refresh_event(lv_event_t* event)
|
||||
{
|
||||
struct tm* ct = lv_event_get_param(event);
|
||||
lvc_calendar_t* cal = lv_event_get_user_data(event);
|
||||
|
||||
style_calendar(cal, ct);
|
||||
}
|
||||
|
255
src/ui/calendar.cpp
Normal file
255
src/ui/calendar.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
#include "date_utils.h"
|
||||
#include "calendar.h"
|
||||
#include "fonts.h"
|
||||
|
||||
|
||||
static lv_style_t box_style;
|
||||
static lv_style_t box_style_active;
|
||||
static lv_style_t box_style_inactive;
|
||||
|
||||
static const char* const month_list[] = {
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
};
|
||||
|
||||
static const char* const event_format_strs[] = {
|
||||
NF_SYMBOL_CAMERA " %d meeting(s)",
|
||||
NF_SYMBOL_UPDATE " %d cascade(s)",
|
||||
NF_SYMBOL_LAPTOP " %d setup(s)",
|
||||
NF_SYMBOL_CALENDAR " %d appointment(s)",
|
||||
NF_SYMBOL_CALENDAR_QUESTION " %d other event(s)",
|
||||
};
|
||||
|
||||
|
||||
void draw_event_list_cb(lv_event_t* event);
|
||||
void calendar_refresh_event(lv_event_t* event);
|
||||
|
||||
|
||||
|
||||
static inline void init_style(uint32_t box_width, uint32_t box_height)
|
||||
{
|
||||
lv_style_init(&box_style);
|
||||
lv_style_set_width(&box_style, box_width);
|
||||
lv_style_set_height(&box_style, box_height);
|
||||
lv_style_set_radius(&box_style, 0);
|
||||
lv_style_set_bg_color(&box_style, lv_color_hex(0xffffff));
|
||||
lv_style_set_bg_opa(&box_style, LV_OPA_COVER);
|
||||
lv_style_set_border_width(&box_style, 2);
|
||||
lv_style_set_border_color(&box_style, lv_color_hex(0x333333));
|
||||
lv_style_set_pad_all(&box_style, 5);
|
||||
|
||||
lv_style_init(&box_style_active);
|
||||
lv_style_set_bg_color(&box_style_active, lv_color_hex(0xbbbbbb));
|
||||
lv_style_set_text_color(&box_style_active, lv_color_hex(0x000000));
|
||||
|
||||
lv_style_init(&box_style_inactive);
|
||||
lv_style_set_bg_color(&box_style_inactive, lv_color_hex(0x646464));
|
||||
}
|
||||
|
||||
Calendar::Calendar(lv_obj_t* parent, uint32_t width)
|
||||
: width(width - (width % 7))
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
struct tm* ct = localtime(&t);
|
||||
|
||||
calendar = lv_obj_create(parent);
|
||||
title_bar = lv_obj_create(calendar);
|
||||
title_label = lv_label_create(title_bar);
|
||||
box_width = width / 7;
|
||||
box_height = box_width * 0.8;
|
||||
|
||||
init_style(box_width, box_height);
|
||||
|
||||
for (uint8_t i = 0; i < CALENDAR_ROWS; i++) {
|
||||
rows[i] = new CalendarRow(calendar);
|
||||
}
|
||||
|
||||
Style(ct);
|
||||
|
||||
lv_obj_add_event_cb(calendar, calendar_refresh_event, LV_EVENT_REFRESH, this);
|
||||
}
|
||||
|
||||
CalendarRow::CalendarRow(lv_obj_t* parent)
|
||||
{
|
||||
for (uint8_t i = 0; i < DAYS_IN_WEEK; i++) {
|
||||
boxes[i] = new CalendarBox(parent);
|
||||
}
|
||||
}
|
||||
|
||||
CalendarBox::CalendarBox(lv_obj_t* parent)
|
||||
{
|
||||
box = lv_obj_create(parent);
|
||||
label = lv_label_create(box);
|
||||
|
||||
for (size_t i = 0; i < Events::EVENTS_COUNT; i++) {
|
||||
event_count_labels[i] = lv_label_create(box);
|
||||
}
|
||||
}
|
||||
|
||||
Calendar::~Calendar()
|
||||
{
|
||||
for (uint8_t i = 0; i < CALENDAR_ROWS; i++) {
|
||||
delete rows[i];
|
||||
}
|
||||
|
||||
lv_obj_delete(title_label);
|
||||
lv_obj_delete(title_bar);
|
||||
lv_obj_delete(calendar);
|
||||
}
|
||||
|
||||
CalendarRow::~CalendarRow()
|
||||
{
|
||||
for (uint8_t i = 0; i < DAYS_IN_WEEK; i++) {
|
||||
delete boxes[i];
|
||||
}
|
||||
}
|
||||
|
||||
CalendarBox::~CalendarBox()
|
||||
{
|
||||
lv_obj_delete(label);
|
||||
|
||||
for (size_t i = 0; i < Events::EVENTS_COUNT; i++) {
|
||||
lv_obj_delete(event_count_labels[i]);
|
||||
}
|
||||
|
||||
lv_obj_delete(box);
|
||||
}
|
||||
|
||||
void Calendar::Style(const struct tm* const ct)
|
||||
{
|
||||
int days = daysInMonth(ct->tm_mon, ct->tm_year + 1900);
|
||||
int start_day = 1 - firstDayOfMonth(ct->tm_mon, ct->tm_year + 1900);
|
||||
|
||||
if (start_day == -5 && days == 31) {
|
||||
start_day += 7;
|
||||
}
|
||||
|
||||
lv_obj_set_size(calendar, width, box_height * 6);
|
||||
lv_obj_set_style_pad_all(calendar, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(calendar, 0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style_all(title_bar);
|
||||
lv_obj_set_size(title_bar, width, box_height);
|
||||
lv_obj_align(title_bar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_pad_all(title_bar, 0, LV_PART_MAIN);
|
||||
lv_obj_add_style(title_bar, &box_style, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style_all(title_label);
|
||||
lv_label_set_text_fmt(title_label, "%s %d", month_list[ct->tm_mon], ct->tm_year + 1900);
|
||||
lv_obj_set_style_text_font(title_label, &lv_font_montserrat_48, LV_PART_MAIN);
|
||||
lv_obj_center(title_label);
|
||||
|
||||
Events::unregisterCallbacks();
|
||||
|
||||
lv_obj_t* last_row = title_bar;
|
||||
for (uint8_t r = 0; r < CALENDAR_ROWS; r++) {
|
||||
start_day = rows[r]->Style(last_row, box_width, box_height, start_day, ct->tm_mday, days);
|
||||
last_row = rows[r]->boxes[0]->box;
|
||||
}
|
||||
|
||||
// Update events, so it will call our callbacks set in style_box to show the list of events
|
||||
Events::update(ct->tm_mday, ct->tm_mon, ct->tm_year + 1900);
|
||||
}
|
||||
|
||||
int CalendarRow::Style(lv_obj_t* last_row, uint32_t box_width, uint32_t box_height, int day, int current_day, int days_in_month)
|
||||
{
|
||||
boxes[0]->Style(box_width, box_height, day, 0, day == current_day, days_in_month);
|
||||
lv_obj_align_to(boxes[0]->box, last_row, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
day++;
|
||||
|
||||
lv_obj_t* last = boxes[0]->box;
|
||||
for (uint8_t i = 1; i < DAYS_IN_WEEK; i++) {
|
||||
boxes[i]->Style(box_width, box_height, day, i, day == current_day, days_in_month);
|
||||
lv_obj_align_to(boxes[i]->box, last, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
|
||||
last = boxes[i]->box;
|
||||
day++;
|
||||
}
|
||||
|
||||
return day;
|
||||
}
|
||||
|
||||
void CalendarBox::Style(uint32_t width, uint32_t height, int day, int wday, bool today, int days_in_month)
|
||||
{
|
||||
lv_obj_remove_style_all(box);
|
||||
lv_obj_set_size(box, width, height);
|
||||
|
||||
lv_obj_add_style(box, &box_style, LV_PART_MAIN);
|
||||
if (today) {
|
||||
lv_obj_add_style(box, &box_style_active, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
if (wday == 6) {
|
||||
lv_obj_set_style_border_side(box, LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_LEFT | LV_BORDER_SIDE_RIGHT, LV_PART_MAIN);
|
||||
} else {
|
||||
lv_obj_set_style_border_side(box, LV_BORDER_SIDE_BOTTOM | LV_BORDER_SIDE_LEFT, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
|
||||
lv_obj_align(label, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
if (day > 0 && day <= days_in_month) {
|
||||
lv_label_set_text_fmt(label, "%d", day);
|
||||
lv_obj_set_style_pad_bottom(label, 8, LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(box, CalendarBox::DrawEvents_cb, LV_EVENT_REFRESH, this);
|
||||
Events::registerCallback(day, box);
|
||||
} else {
|
||||
lv_obj_add_style(box, &box_style_inactive, LV_PART_MAIN);
|
||||
lv_label_set_text(label, "");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < Events::EVENTS_COUNT; i++) {
|
||||
lv_label_set_text(event_count_labels[i], "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CalendarBox::DrawEvents_cb(lv_event_t* event)
|
||||
{
|
||||
Events::event_type_counts* counts = (Events::event_type_counts*) lv_event_get_param(event);
|
||||
CalendarBox* box = (CalendarBox*) lv_event_get_user_data(event);
|
||||
|
||||
int c = 0;
|
||||
lv_obj_t* label = NULL;
|
||||
lv_obj_t* last = box->label;
|
||||
|
||||
for (size_t i = 0; i < Events::EVENTS_COUNT; i++) {
|
||||
c = counts->counts[i];
|
||||
label = box->event_count_labels[i];
|
||||
|
||||
if (c != 0) {
|
||||
lv_label_set_text_fmt(label, event_format_strs[i], c);
|
||||
lv_obj_align_to(label, last, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_style_text_font(label, &nerdfonts_arimo_14, LV_PART_MAIN);
|
||||
last = label;
|
||||
} else {
|
||||
lv_label_set_text(label, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void calendar_refresh_event(lv_event_t* event)
|
||||
{
|
||||
struct tm* ct = (struct tm*) lv_event_get_param(event);
|
||||
Calendar* cal = (Calendar*) lv_event_get_user_data(event);
|
||||
|
||||
cal->Style(ct);
|
||||
}
|
||||
|
@ -1,123 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
#include "events.h"
|
||||
#include "events_panel.h"
|
||||
|
||||
|
||||
int add_event_labels(lvc_events_panel_t* panel, unsigned int count);
|
||||
void draw_events_list_cb(lv_event_t* event);
|
||||
void event_label_set_text(lv_obj_t* label, event_t* event);
|
||||
|
||||
|
||||
lvc_events_panel_t* create_events_panel(lv_obj_t* parent)
|
||||
{
|
||||
lvc_events_panel_t* panel = malloc(sizeof(lvc_events_panel_t));
|
||||
|
||||
panel->panel = lv_obj_create(parent);
|
||||
panel->header = lv_label_create(panel->panel);
|
||||
panel->event_labels = NULL;
|
||||
panel->event_labels_count = 0;
|
||||
|
||||
lv_obj_set_style_pad_all(panel->panel, 10, LV_PART_MAIN);
|
||||
lv_obj_set_scrollbar_mode(panel->panel, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
lv_label_set_text(panel->header, "Events");
|
||||
lv_obj_set_style_text_font(panel->header, &lv_font_montserrat_36, LV_PART_MAIN);
|
||||
lv_obj_align(panel->header, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
lv_obj_add_event_cb(panel->panel, draw_events_list_cb, LV_EVENT_REFRESH, panel);
|
||||
|
||||
register_update_on_detailed_events_change(panel->panel);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
void destroy_events_panel(lvc_events_panel_t* panel)
|
||||
{
|
||||
lv_obj_delete(panel->header);
|
||||
|
||||
for (size_t i = 0; i < panel->event_labels_count; i++) {
|
||||
lv_obj_delete(panel->event_labels[i]);
|
||||
}
|
||||
|
||||
lv_obj_delete(panel->panel);
|
||||
|
||||
free(panel);
|
||||
}
|
||||
|
||||
int add_event_labels(lvc_events_panel_t* panel, unsigned int count)
|
||||
{
|
||||
uint16_t newCapacity = panel->event_labels_count + count;
|
||||
lv_obj_t** newMem = reallocarray(panel->event_labels, newCapacity, sizeof(lv_obj_t*));
|
||||
if (newMem == NULL) {
|
||||
printf("Call to reallocarray failed. Unable to create more labels to display events");
|
||||
return -1;
|
||||
}
|
||||
|
||||
panel->event_labels = newMem;
|
||||
for (size_t i = panel->event_labels_count; i < newCapacity; i++) {
|
||||
panel->event_labels[i] = lv_label_create(panel->panel);
|
||||
}
|
||||
panel->event_labels_count = newCapacity;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void draw_events_list_cb(lv_event_t* event)
|
||||
{
|
||||
lvc_events_panel_t* panel = lv_event_get_user_data(event);
|
||||
events_t* events = lv_event_get_param(event);
|
||||
|
||||
if (panel->event_labels_count < events->size) {
|
||||
// More events than labels. Create new labels for events
|
||||
if (add_event_labels(panel, events->size - panel->event_labels_count) != 0) {
|
||||
printf("Failed to create new labels for event panel\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_t* last = panel->header;
|
||||
size_t i = 0;
|
||||
for (; i < events->size; i++) {
|
||||
event_label_set_text(panel->event_labels[i], &events->events[i]);
|
||||
lv_obj_set_style_text_font(panel->event_labels[i], &lv_font_montserrat_18, LV_PART_MAIN);
|
||||
lv_obj_align_to(panel->event_labels[i], last, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
|
||||
last = panel->event_labels[i];
|
||||
}
|
||||
|
||||
const uint16_t len = panel->event_labels_count;
|
||||
for (;i < len; i++) {
|
||||
lv_obj_delete(panel->event_labels[i]);
|
||||
panel->event_labels_count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void event_label_set_text(lv_obj_t* label, event_t* event)
|
||||
{
|
||||
int s_hour = event->s_hour;
|
||||
const char* const s_time_suffix = s_hour >= 12 ? "PM" : "AM";
|
||||
|
||||
if (s_hour > 12) {
|
||||
s_hour -= 12;
|
||||
}
|
||||
|
||||
if (event->e_hour < 0) {
|
||||
lv_label_set_text_fmt(label, "%s\n%d:%02d %s",
|
||||
event->name, s_hour, event->s_min, s_time_suffix);
|
||||
} else {
|
||||
int e_hour = event->e_hour;
|
||||
const char* const e_time_suffix = e_hour >= 12 ? "PM" : "AM";
|
||||
|
||||
if (e_hour > 12) {
|
||||
e_hour -= 12;
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(label, "%s\n%d:%02d %s - %d:%02d %s",
|
||||
event->name, s_hour, event->s_min, s_time_suffix, e_hour, event->e_min, e_time_suffix);
|
||||
}
|
||||
}
|
||||
|
102
src/ui/events_panel.cpp
Normal file
102
src/ui/events_panel.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include <cstddef>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <vector>
|
||||
|
||||
#include "events.h"
|
||||
#include "events_panel.h"
|
||||
|
||||
|
||||
void setEventLabelText(lv_obj_t* label, Events::Event* event);
|
||||
|
||||
|
||||
EventsPanel::EventsPanel(lv_obj_t* parent)
|
||||
{
|
||||
panel = lv_obj_create(parent);
|
||||
header = lv_label_create(panel);
|
||||
|
||||
lv_obj_set_style_pad_all(panel, 10, LV_PART_MAIN);
|
||||
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
lv_label_set_text(header, "Events");
|
||||
lv_obj_set_style_text_font(header, &lv_font_montserrat_36, LV_PART_MAIN);
|
||||
lv_obj_align(header, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
lv_obj_add_event_cb(panel, EventsPanel::DrawEventList_cb, LV_EVENT_REFRESH, this);
|
||||
|
||||
Events::registerDetailedCallback(panel);
|
||||
}
|
||||
|
||||
EventsPanel::~EventsPanel()
|
||||
{
|
||||
lv_obj_delete(header);
|
||||
|
||||
for (size_t i = 0; i < event_labels.size(); i++) {
|
||||
lv_obj_delete(event_labels[i]);
|
||||
}
|
||||
|
||||
lv_obj_delete(panel);
|
||||
}
|
||||
|
||||
void EventsPanel::DrawEventList_cb(lv_event_t* event)
|
||||
{
|
||||
EventsPanel* panel = (EventsPanel*) lv_event_get_user_data(event);
|
||||
std::vector<Events::Event>* events = (std::vector<Events::Event>*) lv_event_get_param(event);
|
||||
|
||||
if (panel->event_labels.size() < events->size()) {
|
||||
panel->event_labels.reserve(events->size());
|
||||
|
||||
while (panel->event_labels.size() < events->size()) {
|
||||
panel->event_labels.push_back(lv_label_create(panel->panel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t* last = panel->header;
|
||||
size_t i = 0;
|
||||
for (; i < events->size(); i++) {
|
||||
setEventLabelText(panel->event_labels[i], &events->at(i));
|
||||
lv_obj_set_style_text_font(panel->event_labels[i], &lv_font_montserrat_18, LV_PART_MAIN);
|
||||
lv_obj_align_to(panel->event_labels[i], last, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10);
|
||||
last = panel->event_labels[i];
|
||||
}
|
||||
|
||||
|
||||
if (events->size() < panel->event_labels.size()) {
|
||||
for (size_t j = events->size(); j < panel->event_labels.size(); j++) {
|
||||
lv_obj_delete(panel->event_labels[j]);
|
||||
}
|
||||
|
||||
panel->event_labels.erase(std::next(panel->event_labels.begin(), i), panel->event_labels.end());
|
||||
}
|
||||
}
|
||||
|
||||
void setEventLabelText(lv_obj_t* label, Events::Event* event)
|
||||
{
|
||||
int s_hour = event->s_hour;
|
||||
const char* const s_time_suffix = s_hour >= 12 ? "PM" : "AM";
|
||||
|
||||
if (s_hour > 12) {
|
||||
s_hour -= 12;
|
||||
}
|
||||
|
||||
if (event->e_hour < 0) {
|
||||
lv_label_set_text_fmt(label, "%s\n%d:%02d %s",
|
||||
event->name, s_hour, event->s_min, s_time_suffix);
|
||||
} else {
|
||||
int e_hour = event->e_hour;
|
||||
const char* const e_time_suffix = e_hour >= 12 ? "PM" : "AM";
|
||||
|
||||
if (e_hour > 12) {
|
||||
e_hour -= 12;
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(label, "%s\n%d:%02d %s - %d:%02d %s",
|
||||
event->name, s_hour, event->s_min, s_time_suffix, e_hour, event->e_min, e_time_suffix);
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,8 @@
|
||||
static lv_obj_t* screen;
|
||||
static lv_obj_t* time_label;
|
||||
static lv_obj_t* ip_label;
|
||||
static lvc_calendar_t* calendar;
|
||||
static lvc_events_panel_t* events_panel;
|
||||
static Calendar* calendar;
|
||||
static EventsPanel* events_panel;
|
||||
static lv_style_t test_style;
|
||||
|
||||
static char ip_addr[INET_ADDRSTRLEN];
|
||||
@ -60,7 +60,7 @@ void create_widgets(void)
|
||||
lv_label_set_text_fmt(ip_label, "IP: %s", ip_addr);
|
||||
lv_obj_align(ip_label, LV_ALIGN_BOTTOM_LEFT, 5, -5);
|
||||
|
||||
events_panel = create_events_panel(screen);
|
||||
events_panel = new EventsPanel(screen);
|
||||
lv_obj_set_size(events_panel->panel, disp_hpercent_to_px(20), disp_height);
|
||||
lv_obj_align(events_panel->panel, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||
lv_obj_set_style_border_width(events_panel->panel, 2, LV_PART_MAIN);
|
||||
@ -69,7 +69,7 @@ void create_widgets(void)
|
||||
|
||||
// Calendar must be created last. It calls the function to update the events
|
||||
uint32_t cal_width = disp_hpercent_to_px(70);
|
||||
calendar = create_calendar(screen, cal_width);
|
||||
calendar = new Calendar(screen, cal_width);
|
||||
lv_obj_align(calendar->calendar, LV_ALIGN_LEFT_MID, disp_hpercent_to_px(5), 0);
|
||||
|
||||
|
||||
@ -84,8 +84,8 @@ void create_widgets(void)
|
||||
|
||||
void destroy_widgets(void)
|
||||
{
|
||||
destroy_calendar(calendar);
|
||||
destroy_events_panel(events_panel);
|
||||
delete calendar;
|
||||
delete events_panel;
|
||||
|
||||
lv_obj_clean(screen);
|
||||
}
|
||||
@ -119,7 +119,7 @@ void check_time_timer(lv_timer_t* timer)
|
||||
lv_obj_send_event(calendar->calendar, LV_EVENT_REFRESH, ct);
|
||||
} else if (min != ct->tm_min) {
|
||||
min = ct->tm_min;
|
||||
updateEvents(ct->tm_mday, ct->tm_mon, ct->tm_year + 1900);
|
||||
Events::update(ct->tm_mday, ct->tm_mon, ct->tm_year + 1900);
|
||||
|
||||
get_ip(ip_addr, INET_ADDRSTRLEN);
|
||||
lv_label_set_text_fmt(ip_label, "IP: %s", ip_addr);
|
||||
@ -133,13 +133,13 @@ void update_events_timer(lv_timer_t* timer)
|
||||
time_t t = time(NULL);
|
||||
struct tm* ct = localtime(&t);
|
||||
|
||||
updateEvents(ct->tm_mday, ct->tm_mon, ct->tm_year + 1900);
|
||||
Events::update(ct->tm_mday, ct->tm_mon, ct->tm_year + 1900);
|
||||
}
|
||||
|
||||
|
||||
void update_time_label(lv_event_t* event)
|
||||
{
|
||||
struct tm* ct = lv_event_get_param(event);
|
||||
struct tm* ct = (struct tm*) lv_event_get_param(event);
|
||||
|
||||
char time_str[TIME_BUF_LEN];
|
||||
strftime(time_str, TIME_BUF_LEN, "%I:%M:%S %p", ct);
|
Loading…
Reference in New Issue
Block a user