use super::editor::TextEditor; use crate::app::theme; use eframe::egui; pub struct EditorDimensions { pub text_width: f32, pub line_number_width: f32, pub total_reserved_width: f32, } impl TextEditor { pub fn get_title(&self) -> String { if let Some(tab) = self.get_active_tab() { let modified_indicator = if tab.is_modified { "*" } else { "" }; format!("{}{} - C-Text", tab.title, modified_indicator) } else { "C-Text".to_string() } } /// Get the configured font ID based on the editor's font settings fn get_font_id(&self) -> egui::FontId { let font_family = match self.font_family.as_str() { "Monospace" => egui::FontFamily::Monospace, _ => egui::FontFamily::Proportional, }; egui::FontId::new(self.font_size, font_family) } pub fn set_theme(&mut self, ctx: &egui::Context) { theme::apply(self.theme, ctx); self.save_config(); } pub fn apply_font_settings(&mut self, ctx: &egui::Context) { let font_family = match self.font_family.as_str() { "Monospace" => egui::FontFamily::Monospace, _ => egui::FontFamily::Proportional, }; let mut style = (*ctx.style()).clone(); style.text_styles.insert( egui::TextStyle::Monospace, egui::FontId::new(self.font_size, font_family), ); ctx.set_style(style); self.save_config(); } /// Calculates the available width for the text editor, accounting for line numbers and separator pub fn calculate_editor_dimensions(&self, ui: &egui::Ui) -> EditorDimensions { let total_available_width = ui.available_width(); if !self.show_line_numbers { return EditorDimensions { text_width: total_available_width, line_number_width: 0.0, total_reserved_width: 0.0, }; } // Get line count from processing result let processing_result = self.get_text_processing_result(); let line_count = processing_result.line_count; // Calculate base line number width let font_id = self.get_font_id(); let line_count_digits = line_count.to_string().len(); let sample_text = "9".repeat(line_count_digits); let base_line_number_width = ui.fonts(|fonts| { fonts .layout(sample_text, font_id, egui::Color32::WHITE, f32::INFINITY) .size() .x }); // Add padding based on line_side setting let line_number_width = if self.line_side { base_line_number_width + 20.0 // Extra padding when line numbers are on the side } else { base_line_number_width + 8.0 // Minimal padding when line numbers are normal }; // Separator space (7.0 for separator + 3.0 spacing = 10.0 total) let separator_width = 10.0; let total_reserved_width = line_number_width + separator_width; let text_width = (total_available_width - total_reserved_width).max(100.0); // Minimum 100px for text EditorDimensions { text_width, line_number_width, total_reserved_width, } } /// Calculate the available width for non-word-wrapped content based on content analysis pub fn calculate_content_based_width(&self, ui: &egui::Ui) -> f32 { if let Some(active_tab) = self.get_active_tab() { let content = &active_tab.content; if content.is_empty() { return self.calculate_editor_dimensions(ui).text_width; } // Find the longest line let longest_line = content .lines() .max_by_key(|line| line.chars().count()) .unwrap_or(""); if longest_line.is_empty() { return self.calculate_editor_dimensions(ui).text_width; } // Calculate the width needed for the longest line let font_id = self.get_font_id(); let longest_line_width = ui.fonts(|fonts| { fonts.layout( longest_line.to_string(), font_id, egui::Color32::WHITE, f32::INFINITY, ).size().x }) + 20.0; // Add some padding // Return the larger of the calculated width or minimum available width let dimensions = self.calculate_editor_dimensions(ui); longest_line_width.max(dimensions.text_width) } else { self.calculate_editor_dimensions(ui).text_width } } /// Check if width calculation needs to be performed based on parameter changes pub fn needs_width_calculation(&self, ctx: &egui::Context) -> bool { let current_viewport_width = ctx.available_rect().width(); self.cached_width.is_none() || self.word_wrap != self.last_word_wrap || self.show_line_numbers != self.last_show_line_numbers || (self.font_size - self.last_font_size).abs() > 0.1 || self.line_side != self.last_line_side || (current_viewport_width - self.last_viewport_width).abs() > 1.0 } /// Update the cached width calculation state pub fn update_width_calculation_state(&mut self, ctx: &egui::Context, width: f32) { self.cached_width = Some(width); self.last_word_wrap = self.word_wrap; self.last_show_line_numbers = self.show_line_numbers; self.last_font_size = self.font_size; self.last_line_side = self.line_side; self.last_viewport_width = ctx.available_rect().width(); } /// Get cached width if available, otherwise return None to indicate calculation is needed pub fn get_cached_width(&self) -> Option { self.cached_width } }