feat: add scroll bar to Time Zone countries list

This commit is contained in:
2026-05-26 13:58:12 +02:00
parent f2dd09265e
commit 60c1e6858a
+80 -1
View File
@@ -54,6 +54,8 @@ static int g_saved_country = 0;
static int g_saved_zone = 0; static int g_saved_zone = 0;
static int g_country_scroll = 0; static int g_country_scroll = 0;
static int g_zone_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_focus_pane = 0; // 0=country list, 1=zone list
static int g_mouse_x = -1; static int g_mouse_x = -1;
static int g_mouse_y = -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); 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) { static void draw_country_list(Canvas& canvas, const Rect& list, const mtk::Theme& theme) {
draw_list_frame(canvas, list, 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); int rows = visible_rows(list);
for (int row = 0; row < rows; row++) { for (int row = 0; row < rows; row++) {
int index = g_country_scroll + row; int index = g_country_scroll + row;
if (index >= g_country_count) break; 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; bool selected = index == g_selected_country;
mtk::draw_list_row(canvas, item, selected, (index & 1) != 0, theme); 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, canvas.text(item.x + 8, item.y + (item.h - system_font_height()) / 2,
label, selected ? theme.accent_fg : theme.text); 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) { 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); bool clicked = (ev.mouse.buttons & 1) && !(ev.mouse.prev_buttons & 1);
if (!clicked) return redraw; 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)) { if (country.contains(g_mouse_x, g_mouse_y)) {
int row = (g_mouse_y - country.y - 2) / ROW_H; int row = (g_mouse_y - country.y - 2) / ROW_H;
int index = g_country_scroll + row; int index = g_country_scroll + row;