/* * Copyright (C) 2026 Reiner Herrmann * SPDX-License-Identifier: GPL-3.0-or-later */ #include #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(); }