Skip to content

Commit

Permalink
Fix: dragging to above/below a galley will select text to begin/end
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Jan 22, 2024
1 parent 8f52a6e commit 7fda0f5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
6 changes: 3 additions & 3 deletions crates/egui/src/text_selection/cursor_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl CursorRange {

/// Select all the text in a galley
pub fn select_all(galley: &Galley) -> Self {
Self::two(Cursor::default(), galley.end())
Self::two(galley.begin(), galley.end())
}

pub fn as_ccursor_range(&self) -> CCursorRange {
Expand Down Expand Up @@ -342,7 +342,7 @@ fn move_single_cursor(
Key::ArrowUp => {
if modifiers.command {
// mac and windows behavior
*cursor = Cursor::default();
*cursor = galley.begin();
} else {
*cursor = galley.cursor_up_one_row(cursor);
}
Expand All @@ -359,7 +359,7 @@ fn move_single_cursor(
Key::Home => {
if modifiers.ctrl {
// windows behavior
*cursor = Cursor::default();
*cursor = galley.begin();
} else {
*cursor = galley.cursor_begin_of_row(cursor);
}
Expand Down
7 changes: 6 additions & 1 deletion crates/epaint/src/text/cursor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Different types of text cursors, i.e. ways to point into a [`super::Galley`].
/// Character cursor
/// Character cursor.
///
/// The default cursor is zero.
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct CCursor {
Expand Down Expand Up @@ -110,9 +112,12 @@ impl PartialEq for PCursor {
}

/// All different types of cursors together.
///
/// They all point to the same place, but in their own different ways.
/// pcursor/rcursor can also point to after the end of the paragraph/row.
/// Does not implement `PartialEq` because you must think which cursor should be equivalent.
///
/// The default cursor is the zero-cursor, to the first character.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Cursor {
Expand Down
31 changes: 29 additions & 2 deletions crates/epaint/src/text/text_layout_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,16 +712,33 @@ impl Galley {
self.pos_from_pcursor(cursor.pcursor) // pcursor is what TextEdit stores
}

/// Cursor at the given position within the galley
/// Cursor at the given position within the galley.
///
/// A cursor above the galley is considered
/// same as a cursor at the start,
/// and a cursor below the galley is considered
/// same as a cursor at the end.
/// This allows implementing text-selection by dragging above/below the galley.
pub fn cursor_from_pos(&self, pos: Vec2) -> Cursor {
if let Some(first_row) = self.rows.first() {
if pos.y < first_row.min_y() {
return self.begin();
}
}
if let Some(last_row) = self.rows.last() {
if last_row.max_y() < pos.y {
return self.end();
}
}

let mut best_y_dist = f32::INFINITY;
let mut cursor = Cursor::default();

let mut ccursor_index = 0;
let mut pcursor_it = PCursor::default();

for (row_nr, row) in self.rows.iter().enumerate() {
let is_pos_within_row = pos.y >= row.min_y() && pos.y <= row.max_y();
let is_pos_within_row = row.min_y() <= pos.y && pos.y <= row.max_y();
let y_dist = (row.min_y() - pos.y).abs().min((row.max_y() - pos.y).abs());
if is_pos_within_row || y_dist < best_y_dist {
best_y_dist = y_dist;
Expand Down Expand Up @@ -755,12 +772,22 @@ impl Galley {
pcursor_it.offset += row.char_count_including_newline();
}
}

cursor
}
}

/// ## Cursor positions
impl Galley {
/// Cursor to the first character.
///
/// This is the same as [`Cursor::default`].
#[inline]
#[allow(clippy::unused_self)]
pub fn begin(&self) -> Cursor {
Cursor::default()
}

/// Cursor to one-past last character.
pub fn end(&self) -> Cursor {
if self.rows.is_empty() {
Expand Down

0 comments on commit 7fda0f5

Please sign in to comment.