summaryrefslogtreecommitdiff
path: root/src/calendar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/calendar.cpp')
-rw-r--r--src/calendar.cpp133
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++;
+ }
+ }
+}