refactor(tables): FASE 6 - Unificar scrollbars en table_core

- Añadido VerticalScrollbarParams y drawVerticalScrollbar
- Añadido HorizontalScrollbarParams y drawHorizontalScrollbar
- AdvancedTable y VirtualAdvancedTable ahora usan funciones unificadas
- Elimina duplicación de código de renderizado de scrollbars
This commit is contained in:
reugenio 2025-12-27 19:51:56 +01:00
parent 253c9b2449
commit a9caa522a1
3 changed files with 157 additions and 55 deletions

View file

@ -505,27 +505,18 @@ fn drawScrollbar(
const header_h: u32 = if (config.show_headers) config.header_height else 0;
const scrollbar_h = bounds.h -| header_h;
const scrollbar_x = bounds.x + @as(i32, @intCast(bounds.w -| scrollbar_w));
const scrollbar_y = bounds.y + @as(i32, @intCast(header_h));
// Background
ctx.pushCommand(Command.rect(scrollbar_x, scrollbar_y, scrollbar_w, scrollbar_h, colors.border));
// Thumb
const thumb_ratio = @as(f32, @floatFromInt(visible_rows)) / @as(f32, @floatFromInt(total_rows));
const thumb_h = @max(20, @as(u32, @intFromFloat(@as(f32, @floatFromInt(scrollbar_h)) * thumb_ratio)));
const scroll_ratio = @as(f32, @floatFromInt(table_state.nav.scroll_row)) /
@as(f32, @floatFromInt(@max(1, total_rows - visible_rows)));
const thumb_y_offset = @as(u32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(scrollbar_h - thumb_h))));
ctx.pushCommand(Command.rect(
scrollbar_x + 2,
scrollbar_y + @as(i32, @intCast(thumb_y_offset)),
scrollbar_w - 4,
thumb_h,
colors.header_bg,
));
// Usar función unificada de table_core
table_core.drawVerticalScrollbar(ctx, .{
.track_x = bounds.x + @as(i32, @intCast(bounds.w -| scrollbar_w)),
.track_y = bounds.y + @as(i32, @intCast(header_h)),
.width = scrollbar_w,
.height = scrollbar_h,
.visible_count = visible_rows,
.total_count = total_rows,
.scroll_pos = table_state.nav.scroll_row,
.track_color = colors.border,
.thumb_color = colors.header_bg,
});
}
fn drawEditingOverlay(

View file

@ -1332,6 +1332,125 @@ pub fn makeTableDataSource(comptime T: type, impl: *T) TableDataSource {
};
}
// =============================================================================
// Renderizado de Scrollbars (FASE 6)
// =============================================================================
/// Parámetros para dibujar scrollbar vertical
pub const VerticalScrollbarParams = struct {
/// Posición X del track
track_x: i32,
/// Posición Y del track
track_y: i32,
/// Ancho del scrollbar
width: u32 = 12,
/// Altura del track
height: u32,
/// Número de elementos visibles
visible_count: usize,
/// Número total de elementos
total_count: usize,
/// Posición actual del scroll (0-based)
scroll_pos: usize,
/// Color del track (fondo)
track_color: Style.Color,
/// Color del thumb (control deslizante)
thumb_color: Style.Color,
};
/// Dibuja un scrollbar vertical.
/// Función genérica usada por AdvancedTable y VirtualAdvancedTable.
pub fn drawVerticalScrollbar(ctx: *Context, params: VerticalScrollbarParams) void {
if (params.total_count == 0 or params.visible_count >= params.total_count) return;
// Track (fondo)
ctx.pushCommand(Command.rect(
params.track_x,
params.track_y,
params.width,
params.height,
params.track_color,
));
// Calcular tamaño del thumb
const visible_ratio = @as(f32, @floatFromInt(params.visible_count)) /
@as(f32, @floatFromInt(params.total_count));
const thumb_h = @max(20, @as(u32, @intFromFloat(visible_ratio * @as(f32, @floatFromInt(params.height)))));
// Calcular posición del thumb
const max_scroll = params.total_count - params.visible_count;
const scroll_ratio = @as(f32, @floatFromInt(params.scroll_pos)) /
@as(f32, @floatFromInt(@max(1, max_scroll)));
const thumb_y_offset = @as(u32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(params.height - thumb_h))));
// Thumb (control deslizante)
ctx.pushCommand(Command.rect(
params.track_x + 2,
params.track_y + @as(i32, @intCast(thumb_y_offset)),
params.width - 4,
thumb_h,
params.thumb_color,
));
}
/// Parámetros para dibujar scrollbar horizontal
pub const HorizontalScrollbarParams = struct {
/// Posición X del track
track_x: i32,
/// Posición Y del track
track_y: i32,
/// Ancho del track
width: u32,
/// Altura del scrollbar
height: u32 = 12,
/// Ancho visible del contenido
visible_width: u32,
/// Ancho total del contenido
total_width: u32,
/// Posición actual del scroll horizontal (pixels)
scroll_x: i32,
/// Máximo scroll horizontal (pixels)
max_scroll_x: i32,
/// Color del track (fondo)
track_color: Style.Color,
/// Color del thumb (control deslizante)
thumb_color: Style.Color,
};
/// Dibuja un scrollbar horizontal.
/// Función genérica usada por VirtualAdvancedTable.
pub fn drawHorizontalScrollbar(ctx: *Context, params: HorizontalScrollbarParams) void {
if (params.max_scroll_x <= 0) return;
// Track (fondo)
ctx.pushCommand(Command.rect(
params.track_x,
params.track_y,
params.width,
params.height,
params.track_color,
));
// Calcular tamaño del thumb
const visible_ratio = @as(f32, @floatFromInt(params.visible_width)) /
@as(f32, @floatFromInt(params.total_width));
const thumb_w = @max(20, @as(u32, @intFromFloat(visible_ratio * @as(f32, @floatFromInt(params.width)))));
// Calcular posición del thumb
const scroll_ratio = @as(f32, @floatFromInt(params.scroll_x)) /
@as(f32, @floatFromInt(params.max_scroll_x));
const thumb_x_offset = @as(u32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(params.width - thumb_w))));
// Thumb (control deslizante)
ctx.pushCommand(Command.rect(
params.track_x + @as(i32, @intCast(thumb_x_offset)),
params.track_y + 2,
thumb_w,
params.height - 4,
params.thumb_color,
));
}
// =============================================================================
// Tests
// =============================================================================

View file

@ -914,21 +914,18 @@ fn drawScrollbar(
const scrollbar_w: u32 = 12;
const content_h = bounds.h -| header_h -| footer_h;
// Scrollbar track
const track_x = bounds.x + @as(i32, @intCast(bounds.w - scrollbar_w));
const track_y = bounds.y + @as(i32, @intCast(header_h));
ctx.pushCommand(Command.rect(track_x, track_y, scrollbar_w, content_h, colors.row_alternate));
// Thumb size and position
const visible_ratio = @as(f32, @floatFromInt(visible_rows)) / @as(f32, @floatFromInt(total_rows));
const thumb_h = @max(20, @as(u32, @intFromFloat(visible_ratio * @as(f32, @floatFromInt(content_h)))));
const scroll_ratio = @as(f32, @floatFromInt(list_state.nav.scroll_row)) /
@as(f32, @floatFromInt(@max(1, total_rows - visible_rows)));
const thumb_y = track_y + @as(i32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(content_h - thumb_h))));
// Draw thumb
ctx.pushCommand(Command.rect(track_x + 2, thumb_y, scrollbar_w - 4, thumb_h, colors.border));
// Usar función unificada de table_core
table_core.drawVerticalScrollbar(ctx, .{
.track_x = bounds.x + @as(i32, @intCast(bounds.w - scrollbar_w)),
.track_y = bounds.y + @as(i32, @intCast(header_h)),
.width = scrollbar_w,
.height = content_h,
.visible_count = visible_rows,
.total_count = total_rows,
.scroll_pos = list_state.nav.scroll_row,
.track_color = colors.row_alternate,
.thumb_color = colors.border,
});
}
// =============================================================================
@ -946,27 +943,22 @@ fn drawScrollbarH(
colors: *const VirtualAdvancedTableConfig.Colors,
) void {
const scrollbar_v_w: u32 = 12; // Width of vertical scrollbar area
// Scrollbar track position (at the bottom, above footer)
const track_x = bounds.x;
const track_y = bounds.y + @as(i32, @intCast(bounds.h - footer_h - scrollbar_h));
const track_w = bounds.w -| scrollbar_v_w;
const total_width = available_width + @as(u32, @intCast(@max(0, max_scroll_x)));
// Track background
ctx.pushCommand(Command.rect(track_x, track_y, track_w, scrollbar_h, colors.row_alternate));
// Calculate thumb size and position
if (max_scroll_x <= 0) return;
const total_width = available_width + @as(u32, @intCast(max_scroll_x));
const visible_ratio = @as(f32, @floatFromInt(available_width)) / @as(f32, @floatFromInt(total_width));
const thumb_w = @max(20, @as(u32, @intFromFloat(visible_ratio * @as(f32, @floatFromInt(track_w)))));
const scroll_ratio = @as(f32, @floatFromInt(scroll_offset_x)) / @as(f32, @floatFromInt(max_scroll_x));
const thumb_x = track_x + @as(i32, @intFromFloat(scroll_ratio * @as(f32, @floatFromInt(track_w - thumb_w))));
// Draw thumb
ctx.pushCommand(Command.rect(thumb_x, track_y + 2, thumb_w, scrollbar_h - 4, colors.border));
// Usar función unificada de table_core
table_core.drawHorizontalScrollbar(ctx, .{
.track_x = bounds.x,
.track_y = bounds.y + @as(i32, @intCast(bounds.h - footer_h - scrollbar_h)),
.width = track_w,
.height = scrollbar_h,
.visible_width = available_width,
.total_width = total_width,
.scroll_x = scroll_offset_x,
.max_scroll_x = max_scroll_x,
.track_color = colors.row_alternate,
.thumb_color = colors.border,
});
}
// =============================================================================