163 lines
5.9 KiB
Rust
163 lines
5.9 KiB
Rust
|
|
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<f32> {
|
||
|
|
self.cached_width
|
||
|
|
}
|
||
|
|
}
|