mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Simplify the text cursor API (#5785)
<!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * The PR title is what ends up in the changelog, so make it descriptive! * If applicable, add a screenshot or gif. * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`, or a new example. * Do NOT open PR:s from your `master` branch, as that makes it hard for maintainers to test and add commits to your PR. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./scripts/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review your PR, but my time is limited! --> * Closes N/A, but this is part of https://github.com/emilk/egui/issues/3378 * [x] I have followed the instructions in the PR template Other text layout libraries in Rust--namely, Parley and Cosmic Text--have one canonical text cursor type (Parley's is a byte index, Cosmic Text's also stores the line index). To prepare for migrating egui to one of those libraries, it should also have only one text cursor type. I also think simplifying the API is a good idea in and of itself--having three different cursor types that you have to convert between (and a `Cursor` struct which contains all three at once) is confusing. After a bit of experimentation, I found that the best cursor type to coalesce around is `CCursor`. In the few places where we need a paragraph index or row/column position, we can calculate them as necessary. I've removed `CursorRange` and `PCursorRange` (the latter appears to have never been used), merging the functionality with `CCursorRange`. To preserve the cursor position when navigating row-by-row, `CCursorRange` now stores the previous horizontal position of the cursor. I've also removed `PCursor`, and renamed `RowCursor` to `LayoutCursor` (since it includes not only the row but the column). I have not renamed either `CCursorRange` or `CCursor` as those names are used in a lot of places, and I don't want to clutter this PR with a bunch of renames. I'll leave it for a later PR. Finally, I've removed the deprecated methods from `TextEditState`--it made the refactoring easier, and it should be pretty easy to migrate to the equivalent `TextCursorState` methods. I'm not sure how many breaking changes people will actually encounter. A lot of these APIs were technically public, but I don't think many were useful. The `TextBuffer` trait now takes `&CCursorRange` instead of `&CursorRange` in a couple of methods, and I renamed `CCursorRange::sorted` to `CCursorRange::sorted_cursors` to match `CursorRange`. I did encounter a couple of apparent minor bugs when testing out text cursor behavior, but I checked them against the current version of egui and they're all pre-existing.
This commit is contained in:
@@ -26,13 +26,6 @@ impl CCursor {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Cursor> for CCursor {
|
||||
#[inline]
|
||||
fn from(c: Cursor) -> Self {
|
||||
c.ccursor
|
||||
}
|
||||
}
|
||||
|
||||
/// Two `CCursor`s are considered equal if they refer to the same character boundary,
|
||||
/// even if one prefers the start of the next row.
|
||||
impl PartialEq for CCursor {
|
||||
@@ -76,10 +69,12 @@ impl std::ops::SubAssign<usize> for CCursor {
|
||||
}
|
||||
}
|
||||
|
||||
/// Row Cursor
|
||||
/// Row/column cursor.
|
||||
///
|
||||
/// This refers to rows and columns in layout terms--text wrapping creates multiple rows.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct RCursor {
|
||||
pub struct LayoutCursor {
|
||||
/// 0 is first row, and so on.
|
||||
/// Note that a single paragraph can span multiple rows.
|
||||
/// (a paragraph is text separated by `\n`).
|
||||
@@ -90,48 +85,3 @@ pub struct RCursor {
|
||||
/// When moving up/down it may again be within the next row.
|
||||
pub column: usize,
|
||||
}
|
||||
|
||||
/// Paragraph Cursor
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct PCursor {
|
||||
/// 0 is first paragraph, and so on.
|
||||
/// Note that a single paragraph can span multiple rows.
|
||||
/// (a paragraph is text separated by `\n`).
|
||||
pub paragraph: usize,
|
||||
|
||||
/// Character based (NOT bytes).
|
||||
/// It is fine if this points to something beyond the end of the current paragraph.
|
||||
/// When moving up/down it may again be within the next paragraph.
|
||||
pub offset: usize,
|
||||
|
||||
/// If this cursors sits right at the border of a wrapped row break (NOT paragraph break)
|
||||
/// do we prefer the next row?
|
||||
/// This is *almost* always what you want, *except* for when
|
||||
/// explicitly clicking the end of a row or pressing the end key.
|
||||
pub prefer_next_row: bool,
|
||||
}
|
||||
|
||||
/// Two `PCursor`s are considered equal if they refer to the same character boundary,
|
||||
/// even if one prefers the start of the next row.
|
||||
impl PartialEq for PCursor {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.paragraph == other.paragraph && self.offset == other.offset
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
pub ccursor: CCursor,
|
||||
pub rcursor: RCursor,
|
||||
pub pcursor: PCursor,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user