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.
///
/// 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?
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);`"]
pub struct TextEdit<'t, S: TextBuffer = String> {
text: &'t mut S,
pub struct TextEdit<'t> {
text: &'t mut dyn TextBuffer,
hint_text: String,
id: Option<Id>,
id_source: Option<Id>,
@ -271,18 +271,9 @@ pub struct TextEdit<'t, S: TextBuffer = String> {
cursor_at_end: bool,
}
impl<'t, S: TextBuffer> TextEdit<'t, S> {
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> {
impl<'t> TextEdit<'t> {
/// 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 {
desired_height_rows: 1,
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.
pub fn multiline(text: &'t mut S) -> Self {
pub fn multiline(text: &'t mut dyn TextBuffer) -> Self {
Self {
text,
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 {
let is_mutable = self.text.is_mutable();
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 {
let TextEdit {
text,
@ -1038,18 +1038,18 @@ fn byte_index_from_char_index(s: &str, char_index: usize) -> usize {
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);
}
// ----------------------------------------------------------------------------
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();
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);
CCursor {
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 {
let max_ccursor = ccursor;
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])
}
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);
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);
delete_selected_ccursor_range(text, [min_ccursor, max_ccursor])
}
fn delete_paragraph_before_cursor<S: TextBuffer>(
text: &mut S,
fn delete_paragraph_before_cursor(
text: &mut dyn TextBuffer,
galley: &Galley,
cursorp: &CursorPair,
) -> CCursor {
@ -1099,8 +1099,8 @@ fn delete_paragraph_before_cursor<S: TextBuffer>(
}
}
fn delete_paragraph_after_cursor<S: TextBuffer>(
text: &mut S,
fn delete_paragraph_after_cursor(
text: &mut dyn TextBuffer,
galley: &Galley,
cursorp: &CursorPair,
) -> CCursor {
@ -1120,9 +1120,9 @@ fn delete_paragraph_after_cursor<S: TextBuffer>(
// ----------------------------------------------------------------------------
/// Returns `Some(new_cursor)` if we did mutate `text`.
fn on_key_press<S: TextBuffer>(
fn on_key_press(
cursorp: &mut CursorPair,
text: &mut S,
text: &mut dyn TextBuffer,
galley: &Galley,
key: Key,
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 remove_len = if text.as_ref()[line_start.index..].starts_with('\t') {