diff --git a/programs/src/timezone/main.cpp b/programs/src/timezone/main.cpp index 93ab7ec..0b71ac4 100644 --- a/programs/src/timezone/main.cpp +++ b/programs/src/timezone/main.cpp @@ -54,6 +54,8 @@ static int g_saved_country = 0; static int g_saved_zone = 0; static int g_country_scroll = 0; static int g_zone_scroll = 0; +static bool g_country_sb_dragging = false; +static int g_country_sb_drag_offset = 0; static int g_focus_pane = 0; // 0=country list, 1=zone list static int g_mouse_x = -1; static int g_mouse_y = -1; @@ -517,14 +519,43 @@ static void draw_list_frame(Canvas& canvas, const Rect& list, const mtk::Theme& canvas.rect(list.x, list.y, list.w, list.h, theme.border); } +static int country_content_extent() { + return g_country_count * ROW_H; +} + +static int country_view_extent(const Rect& list) { + return visible_rows(list) * ROW_H; +} + +static bool country_scrollbar_visible(const Rect& list) { + return mtk::scrollbar_needed(country_content_extent(), country_view_extent(list)); +} + +static Rect country_scrollbar_track(const Rect& list) { + if (!country_scrollbar_visible(list)) return {0, 0, 0, 0}; + Rect inner = {list.x + 1, list.y + 2, list.w - 2, list.h - 4}; + return mtk::scrollbar_track_rect(inner); +} + +static Rect country_scrollbar_thumb(const Rect& list) { + Rect track = country_scrollbar_track(list); + if (track.empty()) return {0, 0, 0, 0}; + return mtk::scrollbar_thumb_rect(track, + country_content_extent(), + country_view_extent(list), + g_country_scroll * ROW_H); +} + static void draw_country_list(Canvas& canvas, const Rect& list, const mtk::Theme& theme) { draw_list_frame(canvas, list, theme); + bool sb_visible = country_scrollbar_visible(list); + int item_w = list.w - 4 - (sb_visible ? mtk::SCROLLBAR_W : 0); int rows = visible_rows(list); for (int row = 0; row < rows; row++) { int index = g_country_scroll + row; if (index >= g_country_count) break; - Rect item = {list.x + 2, list.y + 2 + row * ROW_H, list.w - 4, ROW_H - 2}; + Rect item = {list.x + 2, list.y + 2 + row * ROW_H, item_w, ROW_H - 2}; bool selected = index == g_selected_country; mtk::draw_list_row(canvas, item, selected, (index & 1) != 0, theme); @@ -533,6 +564,14 @@ static void draw_country_list(Canvas& canvas, const Rect& list, const mtk::Theme canvas.text(item.x + 8, item.y + (item.h - system_font_height()) / 2, label, selected ? theme.accent_fg : theme.text); } + + if (sb_visible) { + Rect track = country_scrollbar_track(list); + Rect thumb = country_scrollbar_thumb(list); + bool hovered = track.contains(g_mouse_x, g_mouse_y) || g_country_sb_dragging; + mtk::draw_scrollbar(canvas, track, thumb, hovered, + g_country_sb_dragging, theme); + } } static void draw_zone_list(Canvas& canvas, const Rect& list, const mtk::Theme& theme) { @@ -680,9 +719,49 @@ static bool handle_mouse(const Montauk::WinEvent& ev) { } } + // Country scrollbar drag + Rect csb_track = country_scrollbar_track(country); + Rect csb_thumb = country_scrollbar_thumb(country); + bool left_held = (ev.mouse.buttons & 1) != 0; + bool just_released = !(ev.mouse.buttons & 1) && (ev.mouse.prev_buttons & 1); + + if (g_country_sb_dragging) { + if (left_held && !csb_track.empty()) { + int thumb_top = g_mouse_y - g_country_sb_drag_offset; + int px_offset = mtk::scrollbar_offset_from_thumb_top( + csb_track, country_content_extent(), + country_view_extent(country), csb_thumb.h, thumb_top); + int new_scroll = px_offset / ROW_H; + if (new_scroll != g_country_scroll) { + g_country_scroll = new_scroll; + clamp_scrolls(); + redraw = true; + } + return redraw; + } + if (just_released) { + g_country_sb_dragging = false; + return true; + } + } + bool clicked = (ev.mouse.buttons & 1) && !(ev.mouse.prev_buttons & 1); if (!clicked) return redraw; + if (!csb_track.empty() && csb_track.contains(g_mouse_x, g_mouse_y)) { + if (csb_thumb.contains(g_mouse_x, g_mouse_y)) { + g_country_sb_dragging = true; + g_country_sb_drag_offset = g_mouse_y - csb_thumb.y; + } else { + int rows = visible_rows(country); + int delta = rows > 1 ? rows - 1 : 1; + if (g_mouse_y < csb_thumb.y) g_country_scroll -= delta; + else g_country_scroll += delta; + clamp_scrolls(); + } + return true; + } + if (country.contains(g_mouse_x, g_mouse_y)) { int row = (g_mouse_y - country.y - 2) / ROW_H; int index = g_country_scroll + row;