feat: use the shared mtk scrollbar in charmap
Replace charmap's hand-drawn scrollbar with the mtk scrollbar widgets (scrollbar_track_rect / scrollbar_thumb_rect / draw_scrollbar), matching the Devices and Music apps: standard 12px track colored SCROLLBAR_BG/FG with a draggable thumb. Adds thumb drag, track-click-to-jump, and hover highlight (mirroring devexplorer's handling); the tile grid reserves an SB_GUTTER on the right sized from mtk::SCROLLBAR_W. The bar auto-hides when the set fits. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -204,7 +204,9 @@ static constexpr int FOOTER_H = 84;
|
||||
static constexpr int GRID_PAD = 12;
|
||||
static constexpr int CELL_GAP = 6;
|
||||
static constexpr int CELL_TARGET = 54; // desired tile edge in px
|
||||
static constexpr int SCROLLBAR_W = 8;
|
||||
// Gutter reserved on the right of the tile area for the shared MTK scrollbar
|
||||
// (its 12px track plus a little breathing room from the last tile column).
|
||||
static constexpr int SB_GUTTER = mtk::SCROLLBAR_W + 6;
|
||||
|
||||
static constexpr int TAB_SIZE = 16;
|
||||
static constexpr int CELL_SIZE = 26; // glyph font size inside a tile
|
||||
@@ -223,6 +225,9 @@ static int g_hover = -1; // hovered glyph index, or -1
|
||||
static bool g_copy_hover = false;
|
||||
static bool g_copy_pressed = false;
|
||||
static int g_scroll = 0; // vertical scroll offset in px
|
||||
static bool g_sb_hover = false; // pointer over the scrollbar track
|
||||
static bool g_sb_dragging = false; // dragging the scrollbar thumb
|
||||
static int g_sb_drag_offset = 0; // grab point within the thumb
|
||||
static uint64_t g_toast_until = 0;
|
||||
static char g_toast[48] = {};
|
||||
|
||||
@@ -255,7 +260,7 @@ static Layout compute_layout(int w, int h) {
|
||||
if (L.grid.w < CELL_TARGET) L.grid.w = CELL_TARGET;
|
||||
if (L.grid.h < 1) L.grid.h = 1;
|
||||
|
||||
int avail = L.grid.w - SCROLLBAR_W;
|
||||
int avail = L.grid.w - SB_GUTTER;
|
||||
if (avail < CELL_TARGET) avail = CELL_TARGET;
|
||||
L.cols = (avail + CELL_GAP) / (CELL_TARGET + CELL_GAP);
|
||||
if (L.cols < 1) L.cols = 1;
|
||||
@@ -286,7 +291,7 @@ static Rect tile_rect(const Layout& L, int i) {
|
||||
|
||||
static int hit_tile(const Layout& L, int mx, int my) {
|
||||
if (my < L.grid.y || my >= L.grid.y + L.grid.h) return -1;
|
||||
if (mx < L.grid.x || mx >= L.grid.x + L.grid.w - SCROLLBAR_W) return -1;
|
||||
if (mx < L.grid.x || mx >= L.grid.x + L.grid.w - SB_GUTTER) return -1;
|
||||
for (int i = 0; i < cur_set().count; i++) {
|
||||
Rect r = tile_rect(L, i);
|
||||
if (r.contains(mx, my)) return i;
|
||||
@@ -380,16 +385,10 @@ static void render(Canvas& c) {
|
||||
draw_centered_glyph(c, r, set.glyphs[i].byte, glyph, CELL_SIZE);
|
||||
}
|
||||
|
||||
// ---- Scrollbar ----
|
||||
if (L.max_scroll > 0 && L.content_h > 0) {
|
||||
int track_x = L.grid.x + L.grid.w - SCROLLBAR_W + 2;
|
||||
int track_h = L.grid.h;
|
||||
int thumb_h = track_h * L.grid.h / L.content_h;
|
||||
if (thumb_h < 24) thumb_h = 24;
|
||||
int thumb_y = L.grid.y + (track_h - thumb_h) * g_scroll / L.max_scroll;
|
||||
c.fill_rounded_rect(track_x, thumb_y, SCROLLBAR_W - 4, thumb_h,
|
||||
(SCROLLBAR_W - 4) / 2, g_theme.border);
|
||||
}
|
||||
// ---- Scrollbar (shared MTK widget; no-ops when the set fits) ----
|
||||
Rect sb_track = mtk::scrollbar_track_rect(L.grid);
|
||||
Rect sb_thumb = mtk::scrollbar_thumb_rect(sb_track, L.content_h, L.grid.h, g_scroll);
|
||||
mtk::draw_scrollbar(c, sb_track, sb_thumb, g_sb_hover, g_sb_dragging, g_theme);
|
||||
|
||||
// ---- Tab bar (opaque) — canonical MontaukOS top-tab style, matching the
|
||||
// Desktop Settings panel (surface bar, window_bg active tab, accent
|
||||
@@ -457,6 +456,15 @@ static bool handle_mouse(const montauk::abi::WinEvent& ev, int w, int h) {
|
||||
|
||||
int mx = ev.mouse.x, my = ev.mouse.y;
|
||||
|
||||
bool left_down = (ev.mouse.buttons & 1) != 0;
|
||||
bool pressed = (ev.mouse.buttons & 1) && !(ev.mouse.prev_buttons & 1);
|
||||
bool released = !(ev.mouse.buttons & 1) && (ev.mouse.prev_buttons & 1);
|
||||
|
||||
// Scrollbar geometry (shared MTK widget).
|
||||
Rect sb_track = mtk::scrollbar_track_rect(L.grid);
|
||||
Rect sb_thumb = mtk::scrollbar_thumb_rect(sb_track, L.content_h, L.grid.h, g_scroll);
|
||||
bool scrollable = !sb_track.empty() && !sb_thumb.empty();
|
||||
|
||||
// Wheel scroll.
|
||||
if (ev.mouse.scroll != 0) {
|
||||
g_scroll -= ev.mouse.scroll * (L.cell_h + CELL_GAP) / 2;
|
||||
@@ -464,6 +472,21 @@ static bool handle_mouse(const montauk::abi::WinEvent& ev, int w, int h) {
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
// Release ends any active thumb drag.
|
||||
if (released && g_sb_dragging) { g_sb_dragging = false; redraw = true; }
|
||||
|
||||
// Active drag follows the pointer.
|
||||
if (g_sb_dragging && left_down && scrollable) {
|
||||
g_scroll = mtk::scrollbar_offset_from_thumb_top(
|
||||
sb_track, L.content_h, L.grid.h, sb_thumb.h, my - g_sb_drag_offset);
|
||||
clamp_scroll(L);
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
// Thumb hover highlight (only meaningful when the set scrolls).
|
||||
bool sb_hover_now = scrollable && sb_track.contains(mx, my);
|
||||
if (sb_hover_now != g_sb_hover) { g_sb_hover = sb_hover_now; redraw = true; }
|
||||
|
||||
int tile = hit_tile(L, mx, my);
|
||||
if (tile != g_hover) { g_hover = tile; redraw = true; }
|
||||
|
||||
@@ -472,11 +495,21 @@ static bool handle_mouse(const montauk::abi::WinEvent& ev, int w, int h) {
|
||||
bool copy_hov = L.copy_btn.contains(mx, my);
|
||||
if (copy_hov != g_copy_hover) { g_copy_hover = copy_hov; redraw = true; }
|
||||
|
||||
bool pressed = (ev.mouse.buttons & 1) && !(ev.mouse.prev_buttons & 1);
|
||||
bool released = !(ev.mouse.buttons & 1) && (ev.mouse.prev_buttons & 1);
|
||||
|
||||
if (pressed) {
|
||||
if (tab >= 0 && tab != g_set) {
|
||||
if (scrollable && sb_thumb.contains(mx, my)) {
|
||||
// Grab the thumb.
|
||||
g_sb_dragging = true;
|
||||
g_sb_drag_offset = my - sb_thumb.y;
|
||||
redraw = true;
|
||||
} else if (scrollable && sb_track.contains(mx, my)) {
|
||||
// Click the track: jump the thumb under the pointer, then drag.
|
||||
g_sb_dragging = true;
|
||||
g_sb_drag_offset = sb_thumb.h / 2;
|
||||
g_scroll = mtk::scrollbar_offset_from_thumb_top(
|
||||
sb_track, L.content_h, L.grid.h, sb_thumb.h, my - sb_thumb.h / 2);
|
||||
clamp_scroll(L);
|
||||
redraw = true;
|
||||
} else if (tab >= 0 && tab != g_set) {
|
||||
g_set = tab;
|
||||
g_sel = 0;
|
||||
g_scroll = 0;
|
||||
@@ -573,6 +606,8 @@ extern "C" void _start() {
|
||||
if (ev.type == 3) break; // close
|
||||
if (ev.type == 2 || ev.type == 4) { // resize / scale
|
||||
g_hover = -1;
|
||||
g_sb_hover = false;
|
||||
g_sb_dragging = false;
|
||||
redraw = true;
|
||||
} else if (ev.type == 1) {
|
||||
redraw = handle_mouse(ev, win.width, win.height);
|
||||
|
||||
Reference in New Issue
Block a user