Skip to content

Commit 948102d

Browse files
committed
Refactor editor sizing/scrolling; fix warnings
Adjust editor UI behavior and clean up unused warnings. - Add #[allow(dead_code)] to PendingAction::ChangeDirectory and DocumentWithHistory::apply_deletions to silence unused warnings. - Remove unused PathBuf import in ui_batch.rs. - Revamp editor interaction in ui_editor.rs: remove manual full-area clickable overlay and custom middle-mouse blocking; rely on TextEdit .min_size() and .interactive(!middle_button_active) instead. - Compute a viewport-based desired_width for wrapping, set TextEdit min_size to fill the visible area, and replace manual auto-scroll trigger with output.response.dragged(). - Clamp scroll offsets to content bounds and remove the custom click-below-content handling; rename line_idx to _line_idx to silence unused-variable warning. These changes simplify control flow, make TextEdit sizing more robust, and eliminate several manual hacks and warnings.
1 parent 1727487 commit 948102d

4 files changed

Lines changed: 35 additions & 51 deletions

File tree

src/app_state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,6 @@ pub enum PendingAction {
5656
OpenDirectory,
5757
Exit,
5858
OpenFileFromTree(PathBuf),
59+
#[allow(dead_code)]
5960
ChangeDirectory(PathBuf),
6061
}

src/history.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ impl DocumentWithHistory {
236236

237237
/// Apply deletions - physically remove deleted entries
238238
/// NOTE: This is NOT used during save anymore - to_file_content() filters automatically
239+
#[allow(dead_code)]
239240
pub fn apply_deletions(&mut self) {
240241
self.history.retain(|entry| !entry.deleted);
241242
}

src/ui_batch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::EditorApp;
22
use eframe::egui;
3-
use std::path::{Path, PathBuf};
3+
use std::path::Path;
44
use crate::crypto::{encrypt_file, decrypt_file};
55

66

src/ui_editor.rs

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,8 @@ impl EditorApp {
111111
// Save scroll area rect for auto-scroll during selection
112112
let scroll_area_rect = ui.clip_rect();
113113

114-
// Create clickable area over the FULL height
115-
let full_area = ui.available_rect_before_wrap();
116-
let sense_rect = ui.interact(
117-
full_area,
118-
ui.id().with("editor_click_area"),
119-
egui::Sense::click(),
120-
);
114+
// Remove manual clickable area over FULL height.
115+
// We will use min_size on the TextEdit instead.
121116

122117
ui.horizontal_top(|ui| {
123118
if show_line_numbers {
@@ -154,7 +149,7 @@ impl EditorApp {
154149

155150
// Iterate lines, including trailing empty line after final \n
156151
let mut lines_iter = text_str.split('\n').peekable();
157-
let mut line_idx = 0;
152+
let mut _line_idx = 0;
158153
while let Some(line) = lines_iter.next() {
159154
let is_last = lines_iter.peek().is_none();
160155

@@ -260,17 +255,13 @@ impl EditorApp {
260255
byte_offset += line.len();
261256
}
262257

263-
line_idx += 1;
258+
_line_idx += 1;
264259
}
265260

266261
ui.fonts(|f| f.layout_job(layout_job))
267262
};
268263

269-
// Add invisible blocking layer during middle mouse
270-
if middle_button_active {
271-
let overlay_rect = ui.max_rect();
272-
ui.allocate_rect(overlay_rect, egui::Sense::click_and_drag());
273-
}
264+
// Panning blocking handled by .interactive(!middle_button_active) in TextEdit
274265

275266
if ui.memory(|mem| mem.has_focus(text_edit_id)) {
276267
if ui.input_mut(|i| i.consume_key(egui::Modifiers::NONE, egui::Key::Tab)) {
@@ -300,18 +291,32 @@ impl EditorApp {
300291
}
301292
}
302293

303-
let available_width = if word_wrap {
304-
ui.available_width()
294+
// Visible viewport width for the text area (excluding line numbers)
295+
let viewport_width = if show_line_numbers {
296+
(full_clip_rect.width() - line_number_width - text_left_padding).max(100.0)
297+
} else {
298+
full_clip_rect.width().max(100.0)
299+
};
300+
301+
// desired_width controls text wrapping:
302+
// word_wrap ON -> wrap at viewport width
303+
// word_wrap OFF -> no wrapping (INFINITY)
304+
let desired_width = if word_wrap {
305+
viewport_width
305306
} else {
306307
f32::INFINITY
307308
};
309+
310+
let min_height = full_clip_rect.height();
308311

309312
let output = egui::TextEdit::multiline(text)
310313
.id(text_edit_id)
311314
.font(egui::TextStyle::Monospace)
312315
.code_editor()
313-
.desired_width(available_width)
316+
.desired_width(desired_width)
314317
.desired_rows(line_count)
318+
// min_size ensures TextEdit fills the visible area but is NEVER infinite
319+
.min_size(egui::vec2(viewport_width, min_height))
315320
.frame(false)
316321
.lock_focus(true)
317322
.interactive(!middle_button_active)
@@ -324,7 +329,7 @@ impl EditorApp {
324329
let galley = &output.galley;
325330

326331
// AUTO-SCROLL during text selection with left button
327-
if pointer.primary_down() && !middle_button_active {
332+
if output.response.dragged() && !middle_button_active {
328333
if let Some(pointer_pos) = pointer.latest_pos() {
329334
let scroll_speed = 15.0;
330335
let scroll_margin = 30.0;
@@ -343,42 +348,19 @@ impl EditorApp {
343348
scroll_state.offset.x += scroll_speed;
344349
}
345350

351+
let content_rect = galley.rect;
352+
let max_offset_y = (content_rect.height() - scroll_area_rect.height()).max(0.0);
353+
let max_offset_x = (content_rect.width() - scroll_area_rect.width()).max(0.0);
354+
scroll_state.offset.y = scroll_state.offset.y.clamp(0.0, max_offset_y);
355+
scroll_state.offset.x = scroll_state.offset.x.clamp(0.0, max_offset_x);
356+
346357
scroll_state.store(ui.ctx(), scroll_id);
347358
}
348359
}
349360

350-
// Calculate content height
351-
let content_height = if !galley.rows.is_empty() {
352-
galley.rows.last().unwrap().max_y()
353-
} else {
354-
0.0
355-
};
356-
let content_bottom = text_rect.min.y + content_height;
357-
358-
// Detect click in empty space BELOW text (only when not middle mouse)
359-
if sense_rect.clicked() && !middle_button_active {
360-
if let Some(pointer_pos) = ui.input(|i| i.pointer.interact_pos()) {
361-
if pointer_pos.y > content_bottom && pointer_pos.x >= text_rect.min.x {
362-
// Clicked below content - move cursor to end
363-
let end_pos = text.chars().count();
364-
if let Some(mut state) =
365-
egui::TextEdit::load_state(ui.ctx(), text_edit_id)
366-
{
367-
state.cursor.set_char_range(Some(
368-
egui::text::CCursorRange::one(egui::text::CCursor::new(
369-
end_pos,
370-
)),
371-
));
372-
state.store(ui.ctx(), text_edit_id);
373-
}
374-
self.highlighted_line = Some(line_count);
375-
ui.memory_mut(|mem| mem.request_focus(text_edit_id));
376-
} else if pointer_pos.y <= content_bottom {
377-
// Clicked within text area - request focus
378-
ui.memory_mut(|mem| mem.request_focus(text_edit_id));
379-
}
380-
}
381-
}
361+
362+
// Removed custom empty-space handling below text,
363+
// as TextEdit now fills the visual area.
382364

383365
// Restore full clip rect for drawing line numbers and separator
384366
ui.set_clip_rect(full_clip_rect);

0 commit comments

Comments
 (0)