summaryrefslogtreecommitdiff
path: root/src/calendar.cpp
blob: 04325b0fa13099cde296f2c2883e4d548ab30155 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <GxEPD2_BW.h>
#include <U8g2_for_Adafruit_GFX.h>
#include <ctime>

#define CELL_SPACING 8

extern GxEPD2_GFX_BASE_CLASS &get_display();
extern U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;

static const char *week_days[] {
	"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So",
};

static const char *months[] {
	"Januar", "Februar", "März", "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;
}

/*
 * @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(int16_t x0, int16_t y0, uint16_t w0, uint16_t h0, uint8_t xoff, uint8_t yoff, String &text, bool highlight = false) {
	uint16_t w = u8g2Fonts.getUTF8Width(text.c_str());
	uint16_t h = 10;  /* assume 10px high font */

	int16_t w_diff = w0 - w;
	int x2 = x0 + xoff * w0 + w_diff/2;
	int y2 = y0 + yoff * h0;

	u8g2Fonts.setCursor(x2, y2);
	u8g2Fonts.print(text);
	if (highlight) {
		get_display().drawCircle(x2 + w/2, y2 - h/2 - 1, w0/2 - 3, GxEPD_BLACK);
	}
}

void draw_calendar(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 */
	u8g2Fonts.setFont(u8g2_font_helvB10_tf);
	uint16_t cell_width, cell_height;
	int w = u8g2Fonts.getUTF8Width(week_days[0]);
	int h = 10;  /* assume 10px high font */
	cell_width = w + CELL_SPACING;
	cell_height = h + CELL_SPACING + 5;

	/* draw title with month and year */
	u8g2Fonts.setFont(u8g2_font_helvB14_tf);
	String title_text = String(months[now.tm_mon]) + " " + String(1900 + now.tm_year);
	draw_cell_content(x0, y0, cell_width * 7, h, 0, 0, title_text);
	y0 += h + 2 * CELL_SPACING;

	/* draw table header with week days */
	u8g2Fonts.setFont(u8g2_font_helvB10_tf);
	for (int i=0; i<7; i++) {
		String week_day = String(week_days[i]);
		draw_cell_content(x0, y0, cell_width, cell_height, i, 0, week_day);
	}

	/* draw days */
	u8g2Fonts.setFont(u8g2_font_helvR10_tf);
	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(x0, y0, cell_width, cell_height, wday, row, day_str, day == now.tm_mday);

		wday++;
		if (wday > 6) {
			wday = 0;
			row++;
		}
	}
}