diff options
Diffstat (limited to 'src/calendar.cpp')
| -rw-r--r-- | src/calendar.cpp | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/calendar.cpp b/src/calendar.cpp new file mode 100644 index 0000000..d743718 --- /dev/null +++ b/src/calendar.cpp @@ -0,0 +1,133 @@ +#include <GxEPD2_BW.h> +#include <Fonts/FreeSansBold12pt7b.h> +#include <Fonts/FreeSansBold9pt7b.h> +#include <Fonts/FreeSans9pt7b.h> +#include <ctime> + +#define CELL_SPACING 10 + +static const char *week_days[] { + "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So", +}; + +static const char *months[] { + "Januar", "Februar", "Maerz", "April", "Mai", "Juni", "Juli", + "August", "September", "Oktober", "November", "Dezember", +}; + +enum month_t { + JANUARY = 0, + FEBRUARY, + MARCH, + APRIL, + MAY, + JUNE, + JULY, + AUGUST, + SEPTEMBER, + OCTOBER, + NOVEMBER, + DECEMBER, +}; + +static int days_in_month(int month, int year) { + switch (month) { + case JANUARY: + case MARCH: + case MAY: + case JULY: + case AUGUST: + case OCTOBER: + case DECEMBER: + return 31; + case APRIL: + case JUNE: + case SEPTEMBER: + case NOVEMBER: + return 30; + case FEBRUARY: + if (year % 400 == 0) return 29; + if (year % 100 == 0) return 28; + if (year % 4 == 0) return 29; + } + assert(month >= 0 && month < 12); + return 0; +} + +/* + * @display where to draw on + * @x0 absolute initial X coord + * @y0 absolute initial Y coord + * @w0 width of a cell + * @h0 height of a cell + * @xoff X pos of cell + * @yoff Y pos of cell + * @text text to draw + * @highlight whether text should be highlighted + */ +static void draw_cell_content(GxEPD2_GFX_BASE_CLASS &display, int16_t x0, int16_t y0, uint16_t w0, uint16_t h0, uint8_t xoff, uint8_t yoff, String &text, bool highlight = false) { + int16_t x, y; + uint16_t w, h; + + display.getTextBounds(text, 0, 0, &x, &y, &w, &h); + + int16_t w_diff = w0 - w; + int x2 = x0 + xoff * w0 + w_diff/2 - x; + int y2 = y0 + yoff * h0 - y; + + display.setCursor(x2, y2); + display.print(text); + if (highlight) { + display.drawCircle(x2 + x + w/2, y2 - h/2, (w0 - CELL_SPACING) / 2, GxEPD_BLACK); + } +} + +void draw_calendar(GxEPD2_GFX_BASE_CLASS &display, int16_t x0, int16_t y0) { + struct tm now; + if (!getLocalTime(&now)) { + return; + } + + uint8_t n_days = days_in_month(now.tm_mon, now.tm_year); + + /* on which weekday is the 1st? */ + int8_t day_of_1st = ((1 - 7 - (now.tm_mday - now.tm_wday)) % 7) + 7; + + /* remap days from So-Sa = 0..6 to Mo-So = 0..6 */ + day_of_1st = (day_of_1st - 1 + 7) % 7; + + /* determine sizes */ + int16_t x, y; + uint16_t w, h, cell_width, cell_height; + display.getTextBounds(week_days[0], 0, 0, &x, &y, &w, &h); + cell_width = w + CELL_SPACING; + cell_height = h + CELL_SPACING; + + /* draw title with month and year */ + display.setFont(&FreeSansBold12pt7b); + String title_text = String(months[now.tm_mon]) + " " + String(1900 + now.tm_year); + draw_cell_content(display, x0, y0, cell_width * 7, h, 0, 0, title_text); + y0 += h + 2 * CELL_SPACING; + + /* draw table header with week days */ + display.setFont(&FreeSansBold9pt7b); + for (int i=0; i<7; i++) { + String week_day = String(week_days[i]); + draw_cell_content(display, x0, y0, cell_width, cell_height, i, 0, week_day); + } + + /* draw days */ + display.setFont(&FreeSans9pt7b); + int8_t wday = day_of_1st; + uint8_t row = 1; + for (uint8_t day = 1; day <= n_days; day++) { + String day_str = String(day); + draw_cell_content(display, x0, y0, cell_width, cell_height, wday, row, day_str, day == now.tm_mday); + + wday++; + if (wday > 6) { + wday = 0; + row++; + } + } +} |
