egui/widgets/text_edit/
state.rs

1use std::sync::Arc;
2
3use crate::mutex::Mutex;
4
5use crate::*;
6
7use self::text_selection::{CCursorRange, CursorRange, TextCursorState};
8
9pub type TextEditUndoer = crate::util::undoer::Undoer<(CCursorRange, String)>;
10
11/// The text edit state stored between frames.
12///
13/// Attention: You also need to `store` the updated state.
14/// ```
15/// # egui::__run_test_ui(|ui| {
16/// # let mut text = String::new();
17/// use egui::text::{CCursor, CCursorRange};
18///
19/// let mut output = egui::TextEdit::singleline(&mut text).show(ui);
20///
21/// // Create a new selection range
22/// let min = CCursor::new(0);
23/// let max = CCursor::new(0);
24/// let new_range = CCursorRange::two(min, max);
25///
26/// // Update the state
27/// output.state.cursor.set_char_range(Some(new_range));
28/// // Store the updated state
29/// output.state.store(ui.ctx(), output.response.id);
30/// # });
31/// ```
32#[derive(Clone, Default)]
33#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
34#[cfg_attr(feature = "serde", serde(default))]
35pub struct TextEditState {
36    /// Controls the text selection.
37    pub cursor: TextCursorState,
38
39    /// Wrapped in Arc for cheaper clones.
40    #[cfg_attr(feature = "serde", serde(skip))]
41    pub(crate) undoer: Arc<Mutex<TextEditUndoer>>,
42
43    // If IME candidate window is shown on this text edit.
44    #[cfg_attr(feature = "serde", serde(skip))]
45    pub(crate) ime_enabled: bool,
46
47    // cursor range for IME candidate.
48    #[cfg_attr(feature = "serde", serde(skip))]
49    pub(crate) ime_cursor_range: CursorRange,
50
51    // Visual offset when editing singleline text bigger than the width.
52    #[cfg_attr(feature = "serde", serde(skip))]
53    pub(crate) singleline_offset: f32,
54
55    /// When did the user last press a key?
56    /// Used to pause the cursor animation when typing.
57    #[cfg_attr(feature = "serde", serde(skip))]
58    pub(crate) last_edit_time: f64,
59}
60
61impl TextEditState {
62    pub fn load(ctx: &Context, id: Id) -> Option<Self> {
63        ctx.data_mut(|d| d.get_persisted(id))
64    }
65
66    pub fn store(self, ctx: &Context, id: Id) {
67        ctx.data_mut(|d| d.insert_persisted(id, self));
68    }
69
70    /// The currently selected range of characters.
71    #[deprecated = "Use `self.cursor.char_range` instead"]
72    pub fn ccursor_range(&self) -> Option<CCursorRange> {
73        self.cursor.char_range()
74    }
75
76    /// Sets the currently selected range of characters.
77    #[deprecated = "Use `self.cursor.set_char_range` instead"]
78    pub fn set_ccursor_range(&mut self, ccursor_range: Option<CCursorRange>) {
79        self.cursor.set_char_range(ccursor_range);
80    }
81
82    #[deprecated = "Use `self.cursor.set_range` instead"]
83    pub fn set_cursor_range(&mut self, cursor_range: Option<CursorRange>) {
84        self.cursor.set_range(cursor_range);
85    }
86
87    pub fn undoer(&self) -> TextEditUndoer {
88        self.undoer.lock().clone()
89    }
90
91    pub fn set_undoer(&mut self, undoer: TextEditUndoer) {
92        *self.undoer.lock() = undoer;
93    }
94
95    pub fn clear_undoer(&mut self) {
96        self.set_undoer(TextEditUndoer::default());
97    }
98
99    #[deprecated = "Use `self.cursor.range` instead"]
100    pub fn cursor_range(&mut self, galley: &Galley) -> Option<CursorRange> {
101        self.cursor.range(galley)
102    }
103}