Compare commits
No commits in common. "7b2ba0603511e7faf2336d59446fc68e90ca1397" and "ab398304779c6962b9c3319f444b05917b93c75a" have entirely different histories.
7b2ba06035
...
ab39830477
2 changed files with 17 additions and 50 deletions
|
|
@ -200,30 +200,16 @@ pub const VirtualListState = struct {
|
||||||
|
|
||||||
/// Mueve la selección hacia arriba
|
/// Mueve la selección hacia arriba
|
||||||
pub fn moveUp(self: *Self) void {
|
pub fn moveUp(self: *Self) void {
|
||||||
const window_offset = self.scroll_offset -| self.window_start;
|
|
||||||
|
|
||||||
if (self.findSelectedInWindow()) |window_idx| {
|
if (self.findSelectedInWindow()) |window_idx| {
|
||||||
// Calcular posición en pantalla actual
|
|
||||||
const screen_pos = window_idx -| window_offset;
|
|
||||||
|
|
||||||
if (window_idx > 0) {
|
if (window_idx > 0) {
|
||||||
// Hay item anterior en buffer, seleccionarlo
|
|
||||||
self.selectByWindowIndex(window_idx - 1);
|
self.selectByWindowIndex(window_idx - 1);
|
||||||
|
} else if (self.window_start > 0) {
|
||||||
// Si estábamos en la primera fila visible, hacer scroll
|
// Necesita scroll up - el widget debe manejar esto
|
||||||
if (screen_pos == 0 and self.scroll_offset > 0) {
|
self.scroll_offset = if (self.scroll_offset > 0) self.scroll_offset - 1 else 0;
|
||||||
self.scroll_offset -= 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Estamos en el inicio del buffer
|
|
||||||
// Scroll up para cargar más datos (si es posible)
|
|
||||||
if (self.scroll_offset > 0) {
|
|
||||||
self.scroll_offset -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (self.current_window.len > 0) {
|
} else if (self.current_window.len > 0) {
|
||||||
// Sin selección: seleccionar primera fila visible
|
// Sin selección: seleccionar primera fila visible
|
||||||
self.selectByWindowIndex(window_offset);
|
self.selectByWindowIndex(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,13 +219,8 @@ pub const VirtualListState = struct {
|
||||||
if (window_idx + 1 < self.current_window.len) {
|
if (window_idx + 1 < self.current_window.len) {
|
||||||
self.selectByWindowIndex(window_idx + 1);
|
self.selectByWindowIndex(window_idx + 1);
|
||||||
|
|
||||||
// Calcular posición en pantalla de la nueva selección
|
// Si la nueva selección está cerca del final visible, scroll
|
||||||
const window_offset = self.scroll_offset -| self.window_start;
|
if (window_idx + 1 >= visible_rows - 1) {
|
||||||
const new_screen_pos = (window_idx + 1) -| window_offset;
|
|
||||||
|
|
||||||
// Scroll cuando la nueva posición llega a la ÚLTIMA fila visible
|
|
||||||
// (visible_rows - 1 es el índice de la última fila, 0-indexed)
|
|
||||||
if (new_screen_pos >= visible_rows) {
|
|
||||||
self.scroll_offset += 1;
|
self.scroll_offset += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ pub fn virtualListRect(
|
||||||
|
|
||||||
// Calculate dimensions
|
// Calculate dimensions
|
||||||
const header_h: u32 = config.row_height;
|
const header_h: u32 = config.row_height;
|
||||||
const footer_h: u32 = if (config.show_count) 16 else 0; // 16px para footer compacto
|
const footer_h: u32 = if (config.show_count) 20 else 0;
|
||||||
const content_h = bounds.h -| header_h -| footer_h;
|
const content_h = bounds.h -| header_h -| footer_h;
|
||||||
const visible_rows: usize = @intCast(content_h / config.row_height);
|
const visible_rows: usize = @intCast(content_h / config.row_height);
|
||||||
|
|
||||||
|
|
@ -173,10 +173,7 @@ pub fn virtualListRect(
|
||||||
drawScrollbar(ctx, bounds, header_h, footer_h, list_state, visible_rows, total_rows, &colors);
|
drawScrollbar(ctx, bounds, header_h, footer_h, list_state, visible_rows, total_rows, &colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw border around the entire list (always visible)
|
// Draw focus ring
|
||||||
ctx.pushCommand(Command.rectOutline(bounds.x, bounds.y, bounds.w, bounds.h, colors.border));
|
|
||||||
|
|
||||||
// Draw focus ring (additional highlight when focused)
|
|
||||||
if (has_focus) {
|
if (has_focus) {
|
||||||
if (Style.isFancy()) {
|
if (Style.isFancy()) {
|
||||||
ctx.pushCommand(Command.focusRing(bounds.x, bounds.y, bounds.w, bounds.h, 4));
|
ctx.pushCommand(Command.focusRing(bounds.x, bounds.y, bounds.w, bounds.h, 4));
|
||||||
|
|
@ -262,7 +259,7 @@ fn drawHeader(
|
||||||
// Column title
|
// Column title
|
||||||
ctx.pushCommand(Command.text(
|
ctx.pushCommand(Command.text(
|
||||||
x + 4,
|
x + 4,
|
||||||
bounds.y + 3, // Centrado vertical mejorado
|
bounds.y + 4,
|
||||||
col.title,
|
col.title,
|
||||||
colors.text,
|
colors.text,
|
||||||
));
|
));
|
||||||
|
|
@ -273,7 +270,7 @@ fn drawHeader(
|
||||||
const indicator = list_state.sort_direction.symbol();
|
const indicator = list_state.sort_direction.symbol();
|
||||||
ctx.pushCommand(Command.text(
|
ctx.pushCommand(Command.text(
|
||||||
x + @as(i32, @intCast(col.width)) - 20,
|
x + @as(i32, @intCast(col.width)) - 20,
|
||||||
bounds.y + 3, // Centrado vertical mejorado
|
bounds.y + 4,
|
||||||
indicator,
|
indicator,
|
||||||
colors.text,
|
colors.text,
|
||||||
));
|
));
|
||||||
|
|
@ -324,19 +321,12 @@ fn drawRows(
|
||||||
|
|
||||||
const row_h = config.row_height;
|
const row_h = config.row_height;
|
||||||
|
|
||||||
// Calculate offset within the window buffer
|
|
||||||
// scroll_offset es la posición global, window_start es donde empieza el buffer
|
|
||||||
const window_offset = list_state.scroll_offset -| list_state.window_start;
|
|
||||||
|
|
||||||
// Draw each visible row
|
// Draw each visible row
|
||||||
var row_idx: usize = 0;
|
var row_idx: usize = 0;
|
||||||
while (row_idx < visible_rows) : (row_idx += 1) {
|
while (row_idx < visible_rows and row_idx < list_state.current_window.len) : (row_idx += 1) {
|
||||||
const data_idx = window_offset + row_idx;
|
|
||||||
if (data_idx >= list_state.current_window.len) break;
|
|
||||||
|
|
||||||
const row_y = content_bounds.y + @as(i32, @intCast(row_idx * row_h));
|
const row_y = content_bounds.y + @as(i32, @intCast(row_idx * row_h));
|
||||||
const global_idx = list_state.scroll_offset + row_idx; // Índice global real
|
const global_idx = list_state.windowToGlobalIndex(row_idx);
|
||||||
const row = list_state.current_window[data_idx];
|
const row = list_state.current_window[row_idx];
|
||||||
|
|
||||||
// Determine row background
|
// Determine row background
|
||||||
const is_selected = list_state.selected_id != null and row.id == list_state.selected_id.?;
|
const is_selected = list_state.selected_id != null and row.id == list_state.selected_id.?;
|
||||||
|
|
@ -369,7 +359,7 @@ fn drawRows(
|
||||||
|
|
||||||
ctx.pushCommand(Command.text(
|
ctx.pushCommand(Command.text(
|
||||||
x + 4,
|
x + 4,
|
||||||
row_y + 3, // Centrado vertical mejorado
|
row_y + 4,
|
||||||
row.values[col_idx],
|
row.values[col_idx],
|
||||||
text_color,
|
text_color,
|
||||||
));
|
));
|
||||||
|
|
@ -508,14 +498,10 @@ fn handleMouseClick(
|
||||||
// Check if click is in content area (not header)
|
// Check if click is in content area (not header)
|
||||||
if (mouse.y >= content_y) {
|
if (mouse.y >= content_y) {
|
||||||
const relative_y = mouse.y - content_y;
|
const relative_y = mouse.y - content_y;
|
||||||
const screen_row = @as(usize, @intCast(relative_y)) / config.row_height;
|
const row_idx = @as(usize, @intCast(relative_y)) / config.row_height;
|
||||||
|
|
||||||
// Convert screen row to buffer index (accounting for scroll)
|
if (row_idx < list_state.current_window.len) {
|
||||||
const window_offset = list_state.scroll_offset -| list_state.window_start;
|
list_state.selectByWindowIndex(row_idx);
|
||||||
const data_idx = window_offset + screen_row;
|
|
||||||
|
|
||||||
if (data_idx < list_state.current_window.len) {
|
|
||||||
list_state.selectById(list_state.current_window[data_idx].id);
|
|
||||||
|
|
||||||
// Check for double click
|
// Check for double click
|
||||||
// TODO: implement double click detection with timing
|
// TODO: implement double click detection with timing
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue