TextEdit: replace monomorphization with &mut dyn TextBuffer

This commit is contained in:
Emil Ernerfeldt 2021-10-02 21:50:24 +02:00
parent 8d854391df
commit 613c0b29f6

View file

@ -118,7 +118,7 @@ impl CCursorPair {
/// an underlying buffer. /// an underlying buffer.
/// ///
/// Most likely you will use a `String` which implements `TextBuffer`. /// Most likely you will use a `String` which implements `TextBuffer`.
pub trait TextBuffer: AsRef<str> + Into<String> { pub trait TextBuffer: AsRef<str> {
/// Can this text be edited? /// Can this text be edited?
fn is_mutable(&self) -> bool; fn is_mutable(&self) -> bool;
@ -253,8 +253,8 @@ impl<'a> TextBuffer for &'a str {
/// ``` /// ```
/// ///
#[must_use = "You should put this widget in an ui with `ui.add(widget);`"] #[must_use = "You should put this widget in an ui with `ui.add(widget);`"]
pub struct TextEdit<'t, S: TextBuffer = String> { pub struct TextEdit<'t> {
text: &'t mut S, text: &'t mut dyn TextBuffer,
hint_text: String, hint_text: String,
id: Option<Id>, id: Option<Id>,
id_source: Option<Id>, id_source: Option<Id>,
@ -271,18 +271,9 @@ pub struct TextEdit<'t, S: TextBuffer = String> {
cursor_at_end: bool, cursor_at_end: bool,
} }
impl<'t, S: TextBuffer> TextEdit<'t, S> { impl<'t> TextEdit<'t> {
pub fn cursor(ui: &Ui, id: Id) -> Option<CursorPair> {
ui.memory()
.id_data
.get::<State>(&id)
.and_then(|state| state.cursorp)
}
}
impl<'t, S: TextBuffer> TextEdit<'t, S> {
/// No newlines (`\n`) allowed. Pressing enter key will result in the `TextEdit` losing focus (`response.lost_focus`). /// No newlines (`\n`) allowed. Pressing enter key will result in the `TextEdit` losing focus (`response.lost_focus`).
pub fn singleline(text: &'t mut S) -> Self { pub fn singleline(text: &'t mut dyn TextBuffer) -> Self {
Self { Self {
desired_height_rows: 1, desired_height_rows: 1,
multiline: false, multiline: false,
@ -291,7 +282,7 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
} }
/// A `TextEdit` for multiple lines. Pressing enter key will create a new line. /// A `TextEdit` for multiple lines. Pressing enter key will create a new line.
pub fn multiline(text: &'t mut S) -> Self { pub fn multiline(text: &'t mut dyn TextBuffer) -> Self {
Self { Self {
text, text,
hint_text: Default::default(), hint_text: Default::default(),
@ -433,7 +424,16 @@ impl<'t, S: TextBuffer> TextEdit<'t, S> {
} }
} }
impl<'t, S: TextBuffer> Widget for TextEdit<'t, S> { impl<'t> TextEdit<'t> {
pub fn cursor(ui: &Ui, id: Id) -> Option<CursorPair> {
ui.memory()
.id_data
.get::<State>(&id)
.and_then(|state| state.cursorp)
}
}
impl<'t> Widget for TextEdit<'t> {
fn ui(self, ui: &mut Ui) -> Response { fn ui(self, ui: &mut Ui) -> Response {
let is_mutable = self.text.is_mutable(); let is_mutable = self.text.is_mutable();
let frame = self.frame; let frame = self.frame;
@ -507,7 +507,7 @@ fn mask_if_password(is_password: bool, text: &str) -> String {
} }
} }
impl<'t, S: TextBuffer> TextEdit<'t, S> { impl<'t> TextEdit<'t> {
fn content_ui(self, ui: &mut Ui) -> Response { fn content_ui(self, ui: &mut Ui) -> Response {
let TextEdit { let TextEdit {
text, text,
@ -1038,18 +1038,18 @@ fn byte_index_from_char_index(s: &str, char_index: usize) -> usize {
s.len() s.len()
} }
fn insert_text<S: TextBuffer>(ccursor: &mut CCursor, text: &mut S, text_to_insert: &str) { fn insert_text(ccursor: &mut CCursor, text: &mut dyn TextBuffer, text_to_insert: &str) {
ccursor.index += text.insert_text(text_to_insert, ccursor.index); ccursor.index += text.insert_text(text_to_insert, ccursor.index);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
fn delete_selected<S: TextBuffer>(text: &mut S, cursorp: &CursorPair) -> CCursor { fn delete_selected(text: &mut dyn TextBuffer, cursorp: &CursorPair) -> CCursor {
let [min, max] = cursorp.sorted(); let [min, max] = cursorp.sorted();
delete_selected_ccursor_range(text, [min.ccursor, max.ccursor]) delete_selected_ccursor_range(text, [min.ccursor, max.ccursor])
} }
fn delete_selected_ccursor_range<S: TextBuffer>(text: &mut S, [min, max]: [CCursor; 2]) -> CCursor { fn delete_selected_ccursor_range(text: &mut dyn TextBuffer, [min, max]: [CCursor; 2]) -> CCursor {
text.delete_char_range(min.index..max.index); text.delete_char_range(min.index..max.index);
CCursor { CCursor {
index: min.index, index: min.index,
@ -1057,7 +1057,7 @@ fn delete_selected_ccursor_range<S: TextBuffer>(text: &mut S, [min, max]: [CCurs
} }
} }
fn delete_previous_char<S: TextBuffer>(text: &mut S, ccursor: CCursor) -> CCursor { fn delete_previous_char(text: &mut dyn TextBuffer, ccursor: CCursor) -> CCursor {
if ccursor.index > 0 { if ccursor.index > 0 {
let max_ccursor = ccursor; let max_ccursor = ccursor;
let min_ccursor = max_ccursor - 1; let min_ccursor = max_ccursor - 1;
@ -1067,22 +1067,22 @@ fn delete_previous_char<S: TextBuffer>(text: &mut S, ccursor: CCursor) -> CCurso
} }
} }
fn delete_next_char<S: TextBuffer>(text: &mut S, ccursor: CCursor) -> CCursor { fn delete_next_char(text: &mut dyn TextBuffer, ccursor: CCursor) -> CCursor {
delete_selected_ccursor_range(text, [ccursor, ccursor + 1]) delete_selected_ccursor_range(text, [ccursor, ccursor + 1])
} }
fn delete_previous_word<S: TextBuffer>(text: &mut S, max_ccursor: CCursor) -> CCursor { fn delete_previous_word(text: &mut dyn TextBuffer, max_ccursor: CCursor) -> CCursor {
let min_ccursor = ccursor_previous_word(text.as_ref(), max_ccursor); let min_ccursor = ccursor_previous_word(text.as_ref(), max_ccursor);
delete_selected_ccursor_range(text, [min_ccursor, max_ccursor]) delete_selected_ccursor_range(text, [min_ccursor, max_ccursor])
} }
fn delete_next_word<S: TextBuffer>(text: &mut S, min_ccursor: CCursor) -> CCursor { fn delete_next_word(text: &mut dyn TextBuffer, min_ccursor: CCursor) -> CCursor {
let max_ccursor = ccursor_next_word(text.as_ref(), min_ccursor); let max_ccursor = ccursor_next_word(text.as_ref(), min_ccursor);
delete_selected_ccursor_range(text, [min_ccursor, max_ccursor]) delete_selected_ccursor_range(text, [min_ccursor, max_ccursor])
} }
fn delete_paragraph_before_cursor<S: TextBuffer>( fn delete_paragraph_before_cursor(
text: &mut S, text: &mut dyn TextBuffer,
galley: &Galley, galley: &Galley,
cursorp: &CursorPair, cursorp: &CursorPair,
) -> CCursor { ) -> CCursor {
@ -1099,8 +1099,8 @@ fn delete_paragraph_before_cursor<S: TextBuffer>(
} }
} }
fn delete_paragraph_after_cursor<S: TextBuffer>( fn delete_paragraph_after_cursor(
text: &mut S, text: &mut dyn TextBuffer,
galley: &Galley, galley: &Galley,
cursorp: &CursorPair, cursorp: &CursorPair,
) -> CCursor { ) -> CCursor {
@ -1120,9 +1120,9 @@ fn delete_paragraph_after_cursor<S: TextBuffer>(
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/// Returns `Some(new_cursor)` if we did mutate `text`. /// Returns `Some(new_cursor)` if we did mutate `text`.
fn on_key_press<S: TextBuffer>( fn on_key_press(
cursorp: &mut CursorPair, cursorp: &mut CursorPair,
text: &mut S, text: &mut dyn TextBuffer,
galley: &Galley, galley: &Galley,
key: Key, key: Key,
modifiers: &Modifiers, modifiers: &Modifiers,
@ -1365,7 +1365,7 @@ fn find_line_start(text: &str, current_index: CCursor) -> CCursor {
} }
} }
fn decrease_identation<S: TextBuffer>(ccursor: &mut CCursor, text: &mut S) { fn decrease_identation(ccursor: &mut CCursor, text: &mut dyn TextBuffer) {
let line_start = find_line_start(text.as_ref(), *ccursor); let line_start = find_line_start(text.as_ref(), *ccursor);
let remove_len = if text.as_ref()[line_start.index..].starts_with('\t') { let remove_len = if text.as_ref()[line_start.index..].starts_with('\t') {