Compare commits

..

No commits in common. "63daca0827a7f544cbb53c699ad69c5609365e83" and "f17104c08b324ac2f0fe21279bce8b6ce5570ca4" have entirely different histories.

6 changed files with 65 additions and 56 deletions

View file

@ -728,9 +728,6 @@ pub const Context = struct {
animating: bool,
/// False if panel was suppressed - caller should return immediately
should_draw: bool,
/// The actual background color being drawn (for table mimetism)
/// Tables should use this as row_normal to blend seamlessly with panel
derived_bg: Style.Color,
};
/// Draw a complete panel frame with focus transition and 3D effects.
@ -835,12 +832,7 @@ pub const Context = struct {
}
// should_draw = false indica que el panel debe saltar operaciones costosas (BD, widgets)
// derived_bg = color actual del fondo (para mimetismo de tablas)
return .{
.animating = animating,
.should_draw = !burst_suppressed,
.derived_bg = transition.current,
};
return .{ .animating = animating, .should_draw = !burst_suppressed };
}
/// Resize the context

View file

@ -40,6 +40,8 @@
// Types - Enums, structs, constantes
pub const types = @import("types.zig");
// Re-exports de types
pub const table_tips = types.table_tips;
pub const TIP_ROTATION_FRAMES = types.TIP_ROTATION_FRAMES;
pub const MAX_EDIT_BUFFER_SIZE = types.MAX_EDIT_BUFFER_SIZE;
pub const MAX_PENDING_COLUMNS = types.MAX_PENDING_COLUMNS;
pub const MAX_CELL_VALUE_LEN = types.MAX_CELL_VALUE_LEN;

View file

@ -4,10 +4,31 @@
//! - Enums de estado y dirección
//! - Structs de configuración y colores
//! - Constantes globales
//! - Tips proactivos
const std = @import("std");
const Style = @import("../../core/style.zig");
// =============================================================================
// Tips Proactivos (FASE I)
// =============================================================================
/// Tips de atajos de teclado para mostrar en StatusLine
/// Rotan cada ~10 segundos para enseñar atajos al usuario
pub const table_tips = [_][]const u8{
"Tip: F2 o Space para editar celda",
"Tip: Tab/Shift+Tab navega entre celdas",
"Tip: Ctrl+N crea nuevo registro",
"Tip: Ctrl+Delete o Ctrl+B borra registro",
"Tip: Ctrl+Shift+1..9 ordena por columna",
"Tip: Ctrl+Home/End va al inicio/fin",
"Tip: Enter confirma y baja, Escape cancela",
"Tip: Al editar, tecla directa reemplaza todo",
};
/// Frames entre rotación de tips (~10s @ 60fps)
pub const TIP_ROTATION_FRAMES: u32 = 600;
// =============================================================================
// Constantes globales
// =============================================================================

View file

@ -247,53 +247,9 @@ pub fn tabsRect(
total_width += width;
}
// ==========================================================================
// PASS 1: Process input events BEFORE drawing (fix visual lag on click)
// ==========================================================================
// Draw tabs
var tab_x = bar_rect.x;
for (tab_list, 0..) |tab, i| {
if (i >= tab_widths.len) break;
const tab_width = tab_widths[i];
const tab_rect = Layout.Rect.init(tab_x, bar_rect.y, tab_width, config.tab_height);
const is_hovered_input = tab_rect.contains(mouse.x, mouse.y) and !tab.disabled;
// Handle close button click (pass 1)
if (config.show_close and tab.closable) {
const close_x = tab_x + @as(i32, @intCast(tab_width - config.close_size - 8));
const close_y = bar_rect.y + @as(i32, @intCast((config.tab_height - config.close_size) / 2));
const close_rect = Layout.Rect.init(close_x, close_y, config.close_size, config.close_size);
const close_hovered = close_rect.contains(mouse.x, mouse.y);
if (close_hovered) {
state.close_hovered = @intCast(i);
}
if (mouse_pressed and close_hovered) {
result.closed = true;
result.closed_index = i;
}
}
// Handle tab click (pass 1) - update state BEFORE drawing
if (mouse_pressed and is_hovered_input and state.close_hovered != @as(i32, @intCast(i))) {
ctx.requestFocus(widget_id);
if (state.selected != i) {
state.selected = i;
result.changed = true;
result.selected = i;
}
}
tab_x += @as(i32, @intCast(tab_width));
}
// ==========================================================================
// PASS 2: Draw tabs with UPDATED state
// ==========================================================================
tab_x = bar_rect.x;
for (tab_list, 0..) |tab, i| {
if (i >= tab_widths.len) break;
@ -372,20 +328,38 @@ pub fn tabsRect(
const text_y = bar_rect.y + @as(i32, @intCast((config.tab_height - 8) / 2));
ctx.pushCommand(Command.text(tab_x + @as(i32, @intCast(config.padding_h)), text_y, tab.label, text_color));
// Draw close button (events already handled in Pass 1)
// Draw close button
if (config.show_close and tab.closable) {
const close_x = tab_x + @as(i32, @intCast(tab_width - config.close_size - 8));
const close_y = bar_rect.y + @as(i32, @intCast((config.tab_height - config.close_size) / 2));
const close_rect = Layout.Rect.init(close_x, close_y, config.close_size, config.close_size);
const close_hovered = close_rect.contains(mouse.x, mouse.y);
if (close_hovered) {
state.close_hovered = @intCast(i);
}
const close_color = if (close_hovered) colors.close_hover else colors.close_color;
// Draw X
ctx.pushCommand(Command.text(close_x + 3, close_y + 2, "x", close_color));
// Handle close click
if (mouse_pressed and close_hovered) {
result.closed = true;
result.closed_index = i;
}
}
// Note: Tab click handling moved to Pass 1 (before drawing)
// Handle tab click
if (mouse_pressed and is_hovered and state.close_hovered != @as(i32, @intCast(i))) {
ctx.requestFocus(widget_id);
if (state.selected != i) {
state.selected = i;
result.changed = true;
result.selected = i;
}
}
tab_x += @as(i32, @intCast(tab_width));
}

View file

@ -123,6 +123,12 @@ pub const VirtualAdvancedTableState = struct {
/// Indica si hubo doble click este frame
double_clicked: bool = false,
/// Frame counter para animaciones
frame_count: u32 = 0,
/// Índice del tip actual (para tips proactivos rotativos)
tip_index: u8 = 0,
// =========================================================================
// Buffers persistentes para texto formateado (evitar stack buffer escape)
// =========================================================================
@ -275,6 +281,7 @@ pub const VirtualAdvancedTableState = struct {
self.filter_text_changed = false;
self.chip_changed = false;
self.changed_chip_index = null;
self.frame_count +%= 1;
}
// =========================================================================

View file

@ -106,6 +106,9 @@ pub const VirtualAdvancedTableResult = struct {
edited_value: ?[]const u8 = null,
previous_row: ?usize = null,
// Tips
current_tip: ?[]const u8 = null,
pub fn getRowChanges(self: *const VirtualAdvancedTableResult) []const table_core.PendingCellChange {
return self.row_changes[0..self.row_changes_count];
}
@ -425,6 +428,16 @@ pub fn virtualAdvancedTableRect(
}
}
// Tips
list_state.frame_count +%= 1;
if (has_focus and !list_state.isEditing()) {
if (list_state.frame_count % table_core.TIP_ROTATION_FRAMES == 0) {
list_state.tip_index = @intCast((list_state.tip_index + 1) % table_core.table_tips.len);
}
result.current_tip = table_core.table_tips[list_state.tip_index];
}
return result;
}