ced/src/ui/central_panel/editor.rs

233 lines
7.1 KiB
Rust
Raw Normal View History

2025-07-05 14:42:45 -04:00
use crate::app::TextEditor;
use eframe::egui;
use super::find_highlight;
2025-07-15 00:42:01 -04:00
pub(super) fn editor_view_ui(ui: &mut egui::Ui, app: &mut TextEditor) -> egui::Response {
let _current_match_position = app.get_current_match_position();
2025-07-05 14:42:45 -04:00
let show_find = app.show_find;
2025-07-15 00:42:01 -04:00
let _prev_show_find = app.prev_show_find;
2025-07-05 14:42:45 -04:00
let show_preferences = app.show_preferences;
let show_about = app.show_about;
let show_shortcuts = app.show_shortcuts;
let word_wrap = app.word_wrap;
let font_size = app.font_size;
let reset_zoom_key = egui::Id::new("editor_reset_zoom");
2025-07-15 00:42:01 -04:00
let should_reset_zoom = ui
.ctx()
.memory_mut(|mem| mem.data.get_temp::<bool>(reset_zoom_key).unwrap_or(false));
2025-07-05 14:42:45 -04:00
if should_reset_zoom {
app.zoom_factor = 1.0;
ui.ctx().set_zoom_factor(1.0);
ui.ctx().memory_mut(|mem| {
mem.data.insert_temp(reset_zoom_key, false);
});
}
2025-07-15 00:42:01 -04:00
let estimated_width = if !word_wrap {
app.calculate_content_based_width(ui)
} else {
0.0
};
2025-07-05 14:42:45 -04:00
let find_data = if show_find && !app.find_matches.is_empty() {
app.get_active_tab().map(|tab| {
(
2025-07-16 17:20:09 -04:00
tab.content.to_owned(),
app.find_matches.to_owned(),
app.current_match_index,
)
})
} else {
None
};
2025-07-15 00:42:01 -04:00
let Some(active_tab) = app.get_active_tab_mut() else {
return ui.label("No file open, how did you get here?");
};
let bg_color = ui.visuals().extreme_bg_color;
let editor_rect = ui.available_rect_before_wrap();
ui.painter().rect_filled(editor_rect, 0.0, bg_color);
2025-07-05 14:42:45 -04:00
if let Some((content, matches, current_match_index)) = &find_data {
let font_id = ui
.style()
.text_styles
.get(&egui::TextStyle::Monospace)
.unwrap_or(&egui::FontId::monospace(font_size))
2025-07-16 17:20:09 -04:00
.to_owned();
let desired_width = if word_wrap {
ui.available_width()
} else {
f32::INFINITY
};
let temp_galley = ui.fonts(|fonts| {
fonts.layout(
2025-07-16 17:20:09 -04:00
content.to_owned(),
font_id.to_owned(),
ui.visuals().text_color(),
desired_width,
)
});
let text_area_left = editor_rect.left() + 4.0;
let text_area_top = editor_rect.top() + 2.0;
find_highlight::draw_find_highlights(
ui,
content,
matches,
*current_match_index,
&temp_galley,
text_area_left,
text_area_top,
font_size,
);
}
2025-07-15 00:42:01 -04:00
let desired_width = if word_wrap {
ui.available_width()
} else {
f32::INFINITY
};
let text_edit = egui::TextEdit::multiline(&mut active_tab.content)
.frame(false)
.font(egui::TextStyle::Monospace)
.code_editor()
.desired_width(desired_width)
.desired_rows(0)
.lock_focus(!show_find)
2025-07-15 00:42:01 -04:00
.cursor_at_end(false)
.id(egui::Id::new("main_text_editor"));
let output = if word_wrap {
text_edit.show(ui)
} else {
egui::ScrollArea::horizontal()
.auto_shrink([false; 2])
.show(ui, |ui| {
ui.allocate_ui_with_layout(
egui::Vec2::new(estimated_width, ui.available_height()),
egui::Layout::left_to_right(egui::Align::TOP),
|ui| text_edit.show(ui),
)
})
.inner
.inner
};
let content_changed = output.response.changed();
let content_for_processing = if content_changed {
active_tab.update_modified_state();
2025-07-16 17:20:09 -04:00
Some(active_tab.content.to_owned())
2025-07-15 00:42:01 -04:00
} else {
None
};
2025-07-23 12:47:26 -04:00
// Save state cache when content changes (after releasing the borrow)
if content_changed {
if let Err(e) = app.save_state_cache() {
eprintln!("Failed to save state cache: {e}");
}
}
if content_changed && app.show_find && !app.find_query.is_empty() {
app.update_find_matches();
}
2025-07-15 00:42:01 -04:00
let current_cursor_pos = output
.state
.cursor
.char_range()
.map(|range| range.primary.index);
if let Some(content) = content_for_processing {
2025-07-16 17:20:09 -04:00
let previous_content = app.previous_content.to_owned();
2025-07-15 00:42:01 -04:00
let previous_cursor_pos = app.previous_cursor_char_index;
if !previous_content.is_empty() {
if let (Some(prev_cursor_pos), Some(curr_cursor_pos)) =
(previous_cursor_pos, current_cursor_pos)
{
app.process_incremental_change(
&previous_content,
&content,
prev_cursor_pos,
curr_cursor_pos,
2025-07-05 14:42:45 -04:00
ui,
);
}
} else {
app.process_text_for_rendering(&content, ui);
2025-07-05 14:42:45 -04:00
}
2025-07-16 17:20:09 -04:00
app.previous_content = content.to_owned();
2025-07-15 00:42:01 -04:00
app.previous_cursor_char_index = current_cursor_pos;
2025-07-05 14:42:45 -04:00
}
2025-07-16 17:20:09 -04:00
if app.font_settings_changed || app.text_needs_processing {
2025-07-15 09:53:45 -04:00
if let Some(active_tab) = app.get_active_tab() {
2025-07-16 17:20:09 -04:00
let content = active_tab.content.to_owned();
app.process_text_for_rendering(&content, ui);
}
2025-07-16 17:20:09 -04:00
app.font_settings_changed = false;
app.text_needs_processing = false;
}
2025-07-15 00:42:01 -04:00
if !word_wrap {
if let Some(cursor_pos) = current_cursor_pos {
let cursor_moved = Some(cursor_pos) != app.previous_cursor_position;
let text_changed = output.response.changed();
if cursor_moved || text_changed {
if let Some(active_tab) = app.get_active_tab() {
let content = &active_tab.content;
let cursor_line = content
.char_indices()
.take_while(|(byte_pos, _)| *byte_pos < cursor_pos)
.filter(|(_, ch)| *ch == '\n')
.count();
let font_id = ui
.style()
.text_styles
.get(&egui::TextStyle::Monospace)
.unwrap_or(&egui::FontId::monospace(font_size))
2025-07-16 17:20:09 -04:00
.to_owned();
2025-07-15 00:42:01 -04:00
let line_height = ui.fonts(|fonts| fonts.row_height(&font_id));
let y_pos = output.response.rect.top() + (cursor_line as f32 * line_height);
let cursor_rect = egui::Rect::from_min_size(
egui::pos2(output.response.rect.left(), y_pos),
egui::vec2(2.0, line_height),
);
2025-07-05 14:42:45 -04:00
let visible_area = ui.clip_rect();
2025-07-15 00:42:01 -04:00
if !visible_area.intersects(cursor_rect) {
ui.scroll_to_rect(cursor_rect, Some(egui::Align::Center));
}
}
2025-07-05 14:42:45 -04:00
}
2025-07-15 00:42:01 -04:00
app.previous_cursor_position = Some(cursor_pos);
2025-07-05 14:42:45 -04:00
}
}
2025-07-15 00:42:01 -04:00
if !output.response.has_focus()
&& !show_preferences
&& !show_about
&& !show_shortcuts
&& !show_find
{
output.response.request_focus();
}
output.response
2025-07-05 14:42:45 -04:00
}