add default-value via init-storage

This commit is contained in:
temportalflux
2026-07-11 09:31:07 -04:00
parent c1d3deb170
commit 76a02bbc46
4 changed files with 46 additions and 14 deletions
+6 -2
View File
@@ -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.
*/
@@ -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<InitStorage>) -> 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<String>) -> Self {
let storage = super::StringStorage::from(value.into());
self.init_storage = InitStorage::new_typed(move |_cx| storage.clone());
self
}
}
impl InteractiveElement for TextInputElement {
@@ -16,18 +16,24 @@ pub enum TextBoundary {
#[derive(Clone, Default)]
pub struct InitStorage(Option<Rc<dyn Fn(&mut App) -> Box<dyn UnicodeTextStorage>>>);
// TODO: Doesnt yet compile in practice "implementation of Fn is not general enough"
// InitStorage::from(|_cx| Box::new(StringStorage::default()) as Box<dyn UnicodeTextStorage>);
impl<F> From<F> for InitStorage
where
F: 'static + for<'app> Fn(&'app mut App) -> Box<dyn UnicodeTextStorage>,
{
fn from(value: F) -> Self {
Self(Some(Rc::new(value)))
}
}
impl InitStorage {
pub fn new_generic<F>(f: F) -> Self
where
F: 'static + Fn(&mut App) -> Box<dyn UnicodeTextStorage>,
{
Self(Some(Rc::new(f)))
}
pub fn new_typed<F, R>(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<dyn UnicodeTextStorage>
})))
}
pub(super) fn exec(&self, cx: &mut App) -> Box<dyn UnicodeTextStorage> {
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,
@@ -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<InitStorage>) -> 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<String>) -> Self {
let storage = super::StringStorage::from(value.into());
self.init_storage = InitStorage::new_typed(move |_cx| storage.clone());
self
}
}
impl InteractiveElement for EditableTextAreaElement {