diff --git a/crates/gpui_elements/src/editable_text.rs b/crates/gpui_elements/src/editable_text.rs index 4e453a995e..cf7fee6d3f 100644 --- a/crates/gpui_elements/src/editable_text.rs +++ b/crates/gpui_elements/src/editable_text.rs @@ -16,7 +16,7 @@ pub use text_area_element::*; pub use text_area_state::*; /* TODO list -- default-value +- disabled input/area - remove gpuikit based input - cursor blinking - color styling configs @@ -24,5 +24,9 @@ pub use text_area_state::*; - text sanitation - test IME (char palette only available on macos) - unit tests -- disabled input/area +*/ + +/* Open questions: +Is is practical and worthwhile to have separate element and state implementations? +The only real difference is how some input-action handler functions are processed. */ diff --git a/crates/gpui_elements/src/editable_text/input_element.rs b/crates/gpui_elements/src/editable_text/input_element.rs index 339a494577..db5ddcfef0 100644 --- a/crates/gpui_elements/src/editable_text/input_element.rs +++ b/crates/gpui_elements/src/editable_text/input_element.rs @@ -42,10 +42,21 @@ impl TextInputElement { self } + /// Swaps the default storage container (standard String) with a custom initializer of [`UnicodeTextStorage`]. pub fn with_storage(mut self, fn_init: impl Into) -> Self { self.init_storage = fn_init.into(); self } + + /// Swaps the default storage container. The new initializer is a standard String using the provided value. + /// + /// Incompatible with [`with_storage`] (they establish the same internal value). + /// If you initialize custom storage, you should be able to initialize its default value. + pub fn default_value(mut self, value: impl Into) -> Self { + let storage = super::StringStorage::from(value.into()); + self.init_storage = InitStorage::new_typed(move |_cx| storage.clone()); + self + } } impl InteractiveElement for TextInputElement { diff --git a/crates/gpui_elements/src/editable_text/storage.rs b/crates/gpui_elements/src/editable_text/storage.rs index ee4c8ff061..eaaf65e59c 100644 --- a/crates/gpui_elements/src/editable_text/storage.rs +++ b/crates/gpui_elements/src/editable_text/storage.rs @@ -16,18 +16,24 @@ pub enum TextBoundary { #[derive(Clone, Default)] pub struct InitStorage(Option Box>>); -// TODO: Doesnt yet compile in practice "implementation of Fn is not general enough" -// InitStorage::from(|_cx| Box::new(StringStorage::default()) as Box); -impl From for InitStorage -where - F: 'static + for<'app> Fn(&'app mut App) -> Box, -{ - fn from(value: F) -> Self { - Self(Some(Rc::new(value))) - } -} - impl InitStorage { + pub fn new_generic(f: F) -> Self + where + F: 'static + Fn(&mut App) -> Box, + { + Self(Some(Rc::new(f))) + } + + pub fn new_typed(f: F) -> Self + where + F: 'static + Fn(&mut App) -> R, + R: 'static + UnicodeTextStorage, + { + Self(Some(Rc::new(move |cx| { + Box::new(f(cx)) as Box + }))) + } + pub(super) fn exec(&self, cx: &mut App) -> Box { match &self.0 { None => Box::new(StringStorage::default()), @@ -229,7 +235,7 @@ pub trait UnicodeTextStorage { } } -#[derive(Default)] +#[derive(Clone, Default)] pub struct StringStorage { value: String, version: u16, diff --git a/crates/gpui_elements/src/editable_text/text_area_element.rs b/crates/gpui_elements/src/editable_text/text_area_element.rs index 6977c5731b..685ace54fd 100644 --- a/crates/gpui_elements/src/editable_text/text_area_element.rs +++ b/crates/gpui_elements/src/editable_text/text_area_element.rs @@ -41,10 +41,21 @@ impl EditableTextAreaElement { self } + /// Swaps the default storage container (standard String) with a custom initializer of [`UnicodeTextStorage`]. pub fn with_storage(mut self, fn_init: impl Into) -> Self { self.init_storage = fn_init.into(); self } + + /// Swaps the default storage container. The new initializer is a standard String using the provided value. + /// + /// Incompatible with [`with_storage`] (they establish the same internal value). + /// If you initialize custom storage, you should be able to initialize its default value. + pub fn default_value(mut self, value: impl Into) -> Self { + let storage = super::StringStorage::from(value.into()); + self.init_storage = InitStorage::new_typed(move |_cx| storage.clone()); + self + } } impl InteractiveElement for EditableTextAreaElement {