aboutsummaryrefslogtreecommitdiff
path: root/src/c/gw2et.c
diff options
context:
space:
mode:
authorReiner Herrmann <reiner@reiner-h.de>2026-04-16 23:32:12 +0200
committerReiner Herrmann <reiner@reiner-h.de>2026-04-16 23:33:24 +0200
commiteda36888fc9dd54ea7f8e16487626e97ac741869 (patch)
treea859eb87d6861f3188c197cb73a6b434e629c698 /src/c/gw2et.c
initial commit
Diffstat (limited to 'src/c/gw2et.c')
-rw-r--r--src/c/gw2et.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/c/gw2et.c b/src/c/gw2et.c
new file mode 100644
index 0000000..e591868
--- /dev/null
+++ b/src/c/gw2et.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2026 Reiner Herrmann
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <pebble.h>
+#include "event.h"
+
+#define DEFAULT_NUM_EVENTS 30
+
+static Window *main_window;
+static MenuLayer *main_menu;
+
+static uint16_t get_num_rows_callback(MenuLayer *menu_layer, uint16_t section_index, void *context) {
+ // TODO: make this configurable
+ return DEFAULT_NUM_EVENTS;
+}
+
+static int16_t get_cell_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *context) {
+ // TODO: adjust for round displays (large in center, smaller above/below)
+ return 50;
+}
+
+static void draw_row_callback(GContext *ctx, const Layer *cell_layer, MenuIndex *cell_index, void *context) {
+ const struct Gw2Event *event = get_next_event(cell_index->row);
+
+ const int16_t timer_box_width = 40;
+
+ /* event title and region */
+ GRect box = layer_get_bounds(cell_layer);
+ box.size.w -= timer_box_width;
+ box.origin.x += timer_box_width;
+ box.size.h /= 2;
+ graphics_draw_text(ctx, event->name, fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD),
+ box, GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL);
+ box.origin.y += box.size.h;
+ graphics_draw_text(ctx, event->location, fonts_get_system_font(FONT_KEY_GOTHIC_18),
+ box, GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL);
+
+ /* color indicator for region */
+#if defined(PBL_COLOR)
+ GRect color_box = layer_get_bounds(cell_layer);
+ color_box.size.w = timer_box_width - 3;
+ const GColor8 category_color = color_for_category(event->category);
+ graphics_context_set_fill_color(ctx, category_color);
+ graphics_fill_rect(ctx, color_box, 0, 0);
+ graphics_context_set_text_color(ctx, gcolor_legible_over(category_color));
+#endif
+
+ /* remaining minutes until start of event */
+ const int minutes_remaining = minutes_to_event(event);
+ const int hours = minutes_remaining / 60;
+ const int minutes = minutes_remaining % 60;
+ char timebuf[16];
+ snprintf(timebuf, sizeof(timebuf), "%02d:%02d", hours, minutes);
+
+ GRect timer_box = layer_get_bounds(cell_layer);
+ timer_box.origin.x += 2;
+ timer_box.origin.y += 15;
+ timer_box.size.w = timer_box_width - 5;
+ timer_box.size.h -= 15;
+ graphics_draw_text(ctx, timebuf, fonts_get_system_font(FONT_KEY_GOTHIC_18),
+ timer_box, GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL);
+}
+
+static void draw_header_callback(GContext *ctx, const Layer *cell_layer, uint16_t section_index, void *callback_context) {
+ menu_cell_basic_header_draw(ctx, cell_layer, "Upcoming Events");
+}
+
+static int16_t get_header_height_callback(struct MenuLayer *menu_layer, uint16_t section_index, void *callback_context) {
+ return MENU_CELL_BASIC_HEADER_HEIGHT;
+}
+
+static int16_t get_separator_height_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) {
+ return 1;
+}
+
+static void select_callback(struct MenuLayer *menu_layer, MenuIndex *cell_index, void *context) {
+}
+
+static void main_window_load(Window *window) {
+ Layer *window_layer = window_get_root_layer(window);
+ const GRect bounds = layer_get_unobstructed_bounds(window_layer);
+
+ main_menu = menu_layer_create(bounds);
+ menu_layer_set_click_config_onto_window(main_menu, window);
+ menu_layer_set_callbacks(main_menu, NULL, (MenuLayerCallbacks) {
+ .get_num_rows = get_num_rows_callback,
+ .draw_row = draw_row_callback,
+ .get_cell_height = get_cell_height_callback,
+ .get_header_height = get_header_height_callback,
+ .draw_header = draw_header_callback,
+ .select_click = select_callback,
+ .get_separator_height = get_separator_height_callback,
+ });
+
+ layer_add_child(window_layer, menu_layer_get_layer(main_menu));
+}
+
+static void main_window_unload(Window *window) {
+ menu_layer_destroy(main_menu);
+}
+
+static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {
+ update_event_index();
+ menu_layer_reload_data(main_menu);
+}
+
+static void init() {
+ main_window = window_create();
+ window_set_window_handlers(main_window, (WindowHandlers) {
+ .load = main_window_load,
+ .unload = main_window_unload,
+ });
+ window_stack_push(main_window, true);
+
+ tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);
+ init_events();
+}
+
+static void deinit() {
+ tick_timer_service_unsubscribe();
+ window_destroy(main_window);
+ cleanup_events();
+}
+
+int main() {
+ init();
+ app_event_loop();
+ deinit();
+}