gui of canvas is from the canvas crate now

This commit is contained in:
Priec
2025-07-29 19:54:29 +02:00
parent a1fa42e204
commit aec5f80879
13 changed files with 370 additions and 53 deletions

View File

@@ -8,7 +8,7 @@ license.workspace = true
anyhow = { workspace = true }
async-trait = "0.1.88"
common = { path = "../common" }
canvas = { path = "../canvas" }
canvas = { path = "../canvas", features = ["gui"] }
ratatui = { workspace = true }
crossterm = { workspace = true }

View File

@@ -29,6 +29,7 @@ move_up = ["Up"]
move_down = ["Down"]
toggle_sidebar = ["ctrl+t"]
toggle_buffer_list = ["ctrl+b"]
revert = ["space+b+r"]
# MODE SPECIFIC
# READ ONLY MODE
@@ -37,7 +38,6 @@ enter_edit_mode_before = ["i"]
enter_edit_mode_after = ["a"]
previous_entry = ["left","q"]
next_entry = ["right","1"]
revert = ["space+b+r"]
move_left = ["h"]
move_right = ["l"]

View File

@@ -1,9 +1,7 @@
// src/components/form/form.rs
use crate::components::common::autocomplete;
use crate::components::handlers::canvas::render_canvas;
use crate::config::colors::themes::Theme;
use crate::state::app::highlight::HighlightState;
use canvas::CanvasState;
use canvas::{CanvasState, render_canvas, HighlightState}; // CHANGED: Import HighlightState from canvas
use crate::state::pages::form::FormState;
use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Margin, Rect},
@@ -15,14 +13,14 @@ use ratatui::{
pub fn render_form(
f: &mut Frame,
area: Rect,
form_state: &FormState, // <--- CHANGE THIS to the concrete type
form_state: &FormState,
fields: &[&str],
current_field_idx: &usize,
inputs: &[&String],
table_name: &str,
theme: &Theme,
is_edit_mode: bool,
highlight_state: &HighlightState,
highlight_state: &HighlightState, // Now using canvas::HighlightState
total_count: u64,
current_position: u64,
) {
@@ -63,27 +61,23 @@ pub fn render_form(
.alignment(Alignment::Left);
f.render_widget(count_para, main_layout[0]);
// Get the active field's rect from render_canvas
let active_field_rect = crate::components::handlers::canvas::render_canvas_library(
// Use the canvas library's render_canvas function
let active_field_rect = render_canvas(
f,
main_layout[1],
form_state,
fields,
current_field_idx,
inputs,
theme,
is_edit_mode,
highlight_state,
);
// --- NEW: RENDER AUTOCOMPLETE ---
// --- RENDER AUTOCOMPLETE ---
if form_state.autocomplete_active {
if let Some(active_rect) = active_field_rect {
let selected_index = form_state.get_selected_suggestion_index();
if let Some(rich_suggestions) = form_state.get_rich_suggestions() {
if !rich_suggestions.is_empty() {
// CHANGE THIS to call the renamed function
autocomplete::render_hit_autocomplete_dropdown(
f,
active_rect,
@@ -95,8 +89,6 @@ pub fn render_form(
);
}
}
// The fallback to simple suggestions is now correctly handled
// because the original render_autocomplete_dropdown exists again.
else if let Some(simple_suggestions) = form_state.get_suggestions() {
if !simple_suggestions.is_empty() {
autocomplete::render_autocomplete_dropdown(
@@ -112,4 +104,3 @@ pub fn render_form(
}
}
}

View File

@@ -1,5 +1,6 @@
// src/client/themes/colors.rs
// src/config/colors/themes.rs
use ratatui::style::Color;
use canvas::CanvasTheme;
#[derive(Debug, Clone)]
pub struct Theme {
@@ -74,3 +75,37 @@ impl Default for Theme {
Self::light() // Default to light theme
}
}
impl CanvasTheme for Theme {
fn bg(&self) -> Color {
self.bg
}
fn fg(&self) -> Color {
self.fg
}
fn border(&self) -> Color {
self.border
}
fn accent(&self) -> Color {
self.accent
}
fn secondary(&self) -> Color {
self.secondary
}
fn highlight(&self) -> Color {
self.highlight
}
fn highlight_bg(&self) -> Color {
self.highlight_bg
}
fn warning(&self) -> Color {
self.warning
}
}

View File

@@ -1,8 +1,7 @@
// src/state/pages/form.rs
use crate::config::colors::themes::Theme;
use crate::state::app::highlight::HighlightState;
use canvas::{CanvasState, CanvasAction, ActionContext}; // CHANGED: Use canvas crate
use canvas::{CanvasState, CanvasAction, ActionContext, HighlightState};
use common::proto::komp_ac::search::search_response::Hit;
use ratatui::layout::Rect;
use ratatui::Frame;
@@ -113,7 +112,7 @@ impl FormState {
area: Rect,
theme: &Theme,
is_edit_mode: bool,
highlight_state: &HighlightState,
highlight_state: &HighlightState, // Now using canvas::HighlightState
) {
let fields_str_slice: Vec<&str> =
self.fields().iter().map(|s| *s).collect();
@@ -146,7 +145,7 @@ impl FormState {
} else {
self.current_position = 1;
}
self.deactivate_suggestions(); // CHANGED: Use canvas trait method
self.deactivate_suggestions();
self.link_display_map.clear();
}
@@ -205,12 +204,10 @@ impl FormState {
self.has_unsaved_changes = false;
self.current_field = 0;
self.current_cursor_pos = 0;
self.deactivate_suggestions(); // CHANGED: Use canvas trait method
self.deactivate_suggestions();
self.link_display_map.clear();
}
// REMOVED: deactivate_autocomplete() - now using trait method
// NEW: Keep the rich suggestions methods for compatibility
pub fn get_rich_suggestions(&self) -> Option<&[Hit]> {
if self.autocomplete_active {
@@ -232,45 +229,45 @@ impl CanvasState for FormState {
fn current_field(&self) -> usize {
self.current_field
}
fn current_cursor_pos(&self) -> usize {
self.current_cursor_pos
}
fn has_unsaved_changes(&self) -> bool {
self.has_unsaved_changes
}
fn inputs(&self) -> Vec<&String> {
self.values.iter().collect()
}
fn get_current_input(&self) -> &str {
FormState::get_current_input(self)
}
fn get_current_input_mut(&mut self) -> &mut String {
FormState::get_current_input_mut(self)
}
fn fields(&self) -> Vec<&str> {
self.fields
.iter()
.map(|f| f.display_name.as_str())
.collect()
}
fn set_current_field(&mut self, index: usize) {
if index < self.fields.len() {
self.current_field = index;
}
self.deactivate_suggestions(); // CHANGED: Use canvas trait method
self.deactivate_suggestions();
}
fn set_current_cursor_pos(&mut self, pos: usize) {
self.current_cursor_pos = pos;
}
fn set_has_unsaved_changes(&mut self, changed: bool) {
self.has_unsaved_changes = changed;
}
@@ -312,18 +309,18 @@ impl CanvasState for FormState {
match action {
CanvasAction::SelectSuggestion => {
if let Some(selected_idx) = self.selected_suggestion_index {
if let Some(hit) = self.autocomplete_suggestions.get(selected_idx).cloned() { // ADD .cloned()
if let Some(hit) = self.autocomplete_suggestions.get(selected_idx).cloned() {
// Extract the value from the selected suggestion
if let Ok(content_map) = serde_json::from_str::<HashMap<String, serde_json::Value>>(&hit.content_json) {
let current_field_def = &self.fields[self.current_field];
if let Some(value) = content_map.get(&current_field_def.data_key) {
let new_value = json_value_to_string(value);
let display_name = self.get_display_name_for_hit(&hit); // Calculate first
let display_name = self.get_display_name_for_hit(&hit);
*self.get_current_input_mut() = new_value.clone();
self.set_current_cursor_pos(new_value.len());
self.set_has_unsaved_changes(true);
self.deactivate_suggestions();
return Some(format!("Selected: {}", display_name)); // Use calculated value
return Some(format!("Selected: {}", display_name));
}
}
}

View File

@@ -19,7 +19,8 @@ use crate::config::colors::themes::Theme;
use crate::modes::general::command_navigation::NavigationState;
use crate::state::pages::canvas_state::CanvasState;
use crate::state::app::buffer::BufferState;
use crate::state::app::highlight::HighlightState;
use crate::state::app::highlight::HighlightState as LocalHighlightState; // CHANGED: Alias local version
use canvas::HighlightState as CanvasHighlightState; // CHANGED: Import canvas version with alias
use crate::state::app::state::AppState;
use crate::state::pages::admin::AdminState;
use crate::state::pages::auth::AuthState;
@@ -32,6 +33,15 @@ use ratatui::{
Frame,
};
// Helper function to convert between HighlightState types
fn convert_highlight_state(local: &LocalHighlightState) -> CanvasHighlightState {
match local {
LocalHighlightState::Off => CanvasHighlightState::Off,
LocalHighlightState::Characterwise { anchor } => CanvasHighlightState::Characterwise { anchor: *anchor },
LocalHighlightState::Linewise { anchor_line } => CanvasHighlightState::Linewise { anchor_line: *anchor_line },
}
}
#[allow(clippy::too_many_arguments)]
pub fn render_ui(
f: &mut Frame,
@@ -44,7 +54,7 @@ pub fn render_ui(
buffer_state: &BufferState,
theme: &Theme,
is_event_handler_edit_mode: bool,
highlight_state: &HighlightState,
highlight_state: &LocalHighlightState, // Keep using local version
event_handler_command_input: &str,
event_handler_command_mode_active: bool,
event_handler_command_message: &str,
@@ -69,7 +79,6 @@ pub fn render_ui(
const PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT: u16 = 15;
let mut bottom_area_constraints: Vec<Constraint> = vec![Constraint::Length(status_line_height)];
let command_palette_area_height = if navigation_state.active {
1 + PALETTE_OPTIONS_HEIGHT_FOR_LAYOUT
@@ -129,7 +138,7 @@ pub fn render_ui(
register_state,
app_state,
register_state.current_field() < 4,
highlight_state,
highlight_state, // Uses local version
);
} else if app_state.ui.show_add_table {
render_add_table(
@@ -139,7 +148,7 @@ pub fn render_ui(
app_state,
&mut admin_state.add_table_state,
is_event_handler_edit_mode,
highlight_state,
highlight_state, // Uses local version
);
} else if app_state.ui.show_add_logic {
render_add_logic(
@@ -149,7 +158,7 @@ pub fn render_ui(
app_state,
&mut admin_state.add_logic_state,
is_event_handler_edit_mode,
highlight_state,
highlight_state, // Uses local version
);
} else if app_state.ui.show_login {
render_login(
@@ -159,7 +168,7 @@ pub fn render_ui(
login_state,
app_state,
login_state.current_field() < 2,
highlight_state,
highlight_state, // Uses local version
);
} else if app_state.ui.show_admin {
crate::components::admin::admin_panel::render_admin_panel(
@@ -201,12 +210,14 @@ pub fn render_ui(
.split(form_actual_area)[1]
};
// CHANGED: Convert local HighlightState to canvas HighlightState for FormState
let canvas_highlight_state = convert_highlight_state(highlight_state);
form_state.render(
f,
form_render_area,
theme,
is_event_handler_edit_mode,
highlight_state,
&canvas_highlight_state, // Use converted version
);
}