fix: standardize scrollbars, fix scrollbar in TextEditor
This commit is contained in:
@@ -775,10 +775,10 @@ inline void draw_separator(Canvas& c, int x, int y, int w, const Theme& theme) {
|
||||
}
|
||||
|
||||
static constexpr int SCROLLBAR_W = 12;
|
||||
static constexpr int SCROLLBAR_OUTER_PAD = 4;
|
||||
static constexpr int SCROLLBAR_TRACK_PAD = 8;
|
||||
static constexpr int SCROLLBAR_THUMB_INSET = 2;
|
||||
static constexpr int SCROLLBAR_MIN_THUMB = 24;
|
||||
static constexpr int SCROLLBAR_OUTER_PAD = 0;
|
||||
static constexpr int SCROLLBAR_TRACK_PAD = 0;
|
||||
static constexpr int SCROLLBAR_THUMB_INSET = 1;
|
||||
static constexpr int SCROLLBAR_MIN_THUMB = 20;
|
||||
|
||||
inline bool scrollbar_needed(int content_extent, int view_extent) {
|
||||
return content_extent > view_extent && view_extent > 0;
|
||||
@@ -851,13 +851,11 @@ inline int scrollbar_offset_from_thumb_top(const Rect& track,
|
||||
return (int)(((int64_t)rel * max_offset + travel / 2) / travel);
|
||||
}
|
||||
|
||||
inline Color scrollbar_thumb_color(const Theme& theme,
|
||||
inline Color scrollbar_thumb_color(const Theme& /*theme*/,
|
||||
bool hovered,
|
||||
bool dragging) {
|
||||
Color base = mix(theme.border, theme.text_muted, 54);
|
||||
if (dragging) return mix(base, theme.accent, 118);
|
||||
if (hovered) return mix(base, theme.accent, 42);
|
||||
return base;
|
||||
if (hovered || dragging) return Color::from_rgb(0xA0, 0xA0, 0xA0);
|
||||
return colors::SCROLLBAR_FG;
|
||||
}
|
||||
|
||||
inline void draw_scrollbar(Canvas& c,
|
||||
@@ -868,26 +866,9 @@ inline void draw_scrollbar(Canvas& c,
|
||||
const Theme& theme) {
|
||||
if (track.empty() || thumb.empty()) return;
|
||||
|
||||
if (hovered || dragging) {
|
||||
int rail_w = track.w > 6 ? track.w - 6 : track.w;
|
||||
if (rail_w < 1) rail_w = 1;
|
||||
Rect rail = {
|
||||
track.x + (track.w - rail_w) / 2,
|
||||
track.y,
|
||||
rail_w,
|
||||
track.h
|
||||
};
|
||||
Color rail_fill = dragging
|
||||
? mix(theme.window_bg, theme.accent, 34)
|
||||
: mix(theme.window_bg, theme.text_muted, 24);
|
||||
c.fill_rounded_rect(rail.x, rail.y, rail.w, rail.h,
|
||||
gui_max(theme.radius_sm, rail.w / 2),
|
||||
rail_fill);
|
||||
}
|
||||
|
||||
c.fill_rect(track.x, track.y, track.w, track.h, colors::SCROLLBAR_BG);
|
||||
Color thumb_fill = scrollbar_thumb_color(theme, hovered, dragging);
|
||||
int radius = gui_max(theme.radius_sm, thumb.w / 2);
|
||||
c.fill_rounded_rect(thumb.x, thumb.y, thumb.w, thumb.h, radius, thumb_fill);
|
||||
c.fill_rect(thumb.x, thumb.y, thumb.w, thumb.h, thumb_fill);
|
||||
}
|
||||
|
||||
inline Rect tab_rect(const Rect& bar, int count, int index) {
|
||||
|
||||
@@ -97,6 +97,9 @@ int g_cursor_line = 0;
|
||||
int g_cursor_col = 0;
|
||||
int g_scroll_y = 0; // first visible line
|
||||
int g_scroll_x = 0; // horizontal scroll in pixels
|
||||
bool g_scroll_dragging = false;
|
||||
int g_scroll_drag_offset = 0; // mouse y - thumb_y at drag start
|
||||
bool g_scroll_hovered = false;
|
||||
bool g_modified = false;
|
||||
bool g_cursor_moved = true;
|
||||
char g_status_msg[128] = {};
|
||||
@@ -923,7 +926,10 @@ static void render(uint32_t* pixels) {
|
||||
if (thumb_h < 20) thumb_h = 20;
|
||||
int range = text_area_h - thumb_h;
|
||||
int thumb_y = editor_y + (g_scroll_y * range) / max_scr;
|
||||
px_fill(pixels, W, H, sb_x + 1, thumb_y, SCROLLBAR_W - 2, thumb_h, Color::from_rgb(0xAA, 0xAA, 0xAA));
|
||||
Color thumb_c = (g_scroll_hovered || g_scroll_dragging)
|
||||
? Color::from_rgb(0xA0, 0xA0, 0xA0)
|
||||
: Color::from_rgb(0xC0, 0xC0, 0xC0);
|
||||
px_fill(pixels, W, H, sb_x + 1, thumb_y, SCROLLBAR_W - 2, thumb_h, thumb_c);
|
||||
}
|
||||
|
||||
// ---- Status bar ----
|
||||
@@ -1283,6 +1289,60 @@ static bool handle_mouse(Montauk::WinEvent& ev, int win_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- Scrollbar interaction ----
|
||||
int visible_lines = (cell_h > 0) ? text_area_h / cell_h : 0;
|
||||
int content_h = g_line_count * cell_h;
|
||||
bool sb_visible = content_h > text_area_h && visible_lines > 0;
|
||||
int sb_x = g_win_w - SCROLLBAR_W;
|
||||
int thumb_h = 0, thumb_y = 0, max_scr = 0, range = 0;
|
||||
if (sb_visible) {
|
||||
max_scr = g_line_count - visible_lines;
|
||||
if (max_scr < 1) max_scr = 1;
|
||||
thumb_h = (text_area_h * text_area_h) / content_h;
|
||||
if (thumb_h < 20) thumb_h = 20;
|
||||
range = text_area_h - thumb_h;
|
||||
thumb_y = editor_y + (g_scroll_y * range) / max_scr;
|
||||
}
|
||||
|
||||
bool in_track = sb_visible && mx >= sb_x && mx < sb_x + SCROLLBAR_W
|
||||
&& my >= editor_y && my < editor_y + text_area_h;
|
||||
bool in_thumb = in_track && my >= thumb_y && my < thumb_y + thumb_h;
|
||||
g_scroll_hovered = in_thumb || g_scroll_dragging;
|
||||
|
||||
if (g_scroll_dragging) {
|
||||
if (held) {
|
||||
if (range > 0) {
|
||||
int new_thumb_y = my - g_scroll_drag_offset;
|
||||
int rel = new_thumb_y - editor_y;
|
||||
if (rel < 0) rel = 0;
|
||||
if (rel > range) rel = range;
|
||||
g_scroll_y = (rel * max_scr + range / 2) / range;
|
||||
if (g_scroll_y < 0) g_scroll_y = 0;
|
||||
if (g_scroll_y > max_scr) g_scroll_y = max_scr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (released) {
|
||||
g_scroll_dragging = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (clicked && in_track) {
|
||||
if (in_thumb) {
|
||||
g_scroll_dragging = true;
|
||||
g_scroll_drag_offset = my - thumb_y;
|
||||
} else if (range > 0) {
|
||||
// page jump: click above/below thumb scrolls by one page
|
||||
int delta_lines = visible_lines > 1 ? visible_lines - 1 : 1;
|
||||
if (my < thumb_y) g_scroll_y -= delta_lines;
|
||||
else g_scroll_y += delta_lines;
|
||||
if (g_scroll_y < 0) g_scroll_y = 0;
|
||||
if (g_scroll_y > max_scr) g_scroll_y = max_scr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---- Editor click ----
|
||||
if (right_clicked && my >= editor_y && my < editor_y + text_area_h
|
||||
&& mx > LINE_NUM_W && mx < g_win_w - SCROLLBAR_W) {
|
||||
|
||||
Reference in New Issue
Block a user