mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Cross-widget text select (#3870)
* Closes https://github.com/emilk/egui/issues/3816  Turn off with `style.interaction.multi_widget_text_select`. There is an API for this in `LabelSelectionState`, but it's pretty bare-bones. This became really hairy implementation-wise, but it works decently well. # Limitations * Drag-select to scroll doesn't work * A selection disappears if you scroll past one of its end-points * Only the text of labels and links are selectable ## TODO * [x] An option to turn it off * [x] An API for querying about the selected text, and to deselect it. * [x] Scrolling past selection behaves weird * [x] Shift-click to select a range
This commit is contained in:
@@ -17,6 +17,7 @@ pub struct CCursor {
|
||||
}
|
||||
|
||||
impl CCursor {
|
||||
#[inline]
|
||||
pub fn new(index: usize) -> Self {
|
||||
Self {
|
||||
index,
|
||||
@@ -25,9 +26,17 @@ 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 {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.index == other.index
|
||||
}
|
||||
@@ -106,6 +115,7 @@ pub struct PCursor {
|
||||
/// 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
|
||||
}
|
||||
|
||||
@@ -426,6 +426,9 @@ impl TextWrapping {
|
||||
/// from `egui::InputState` and can change at any time.
|
||||
/// - The atlas has become full. This can happen any time a new glyph is added
|
||||
/// to the atlas, which in turn can happen any time new text is laid out.
|
||||
///
|
||||
/// The name comes from typography, where a "galley" is a metal tray
|
||||
/// containing a column of set type, usually the size of a page of text.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct Galley {
|
||||
@@ -672,6 +675,11 @@ impl Galley {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a 0-width Rect.
|
||||
pub fn pos_from_cursor(&self, cursor: &Cursor) -> Rect {
|
||||
self.pos_from_pcursor(cursor.pcursor) // pcursor is what TextEdit stores
|
||||
}
|
||||
|
||||
/// Returns a 0-width Rect.
|
||||
pub fn pos_from_pcursor(&self, pcursor: PCursor) -> Rect {
|
||||
let mut it = PCursor::default();
|
||||
@@ -708,8 +716,13 @@ impl Galley {
|
||||
}
|
||||
|
||||
/// Returns a 0-width Rect.
|
||||
pub fn pos_from_cursor(&self, cursor: &Cursor) -> Rect {
|
||||
self.pos_from_pcursor(cursor.pcursor) // pcursor is what TextEdit stores
|
||||
pub fn pos_from_ccursor(&self, ccursor: CCursor) -> Rect {
|
||||
self.pos_from_cursor(&self.from_ccursor(ccursor))
|
||||
}
|
||||
|
||||
/// Returns a 0-width Rect.
|
||||
pub fn pos_from_rcursor(&self, rcursor: RCursor) -> Rect {
|
||||
self.pos_from_cursor(&self.from_rcursor(rcursor))
|
||||
}
|
||||
|
||||
/// Cursor at the given position within the galley.
|
||||
|
||||
Reference in New Issue
Block a user