diff --git a/crates/yakui-widgets/src/widgets/textbox.rs b/crates/yakui-widgets/src/widgets/textbox.rs index 9edd384e..c4485ea4 100644 --- a/crates/yakui-widgets/src/widgets/textbox.rs +++ b/crates/yakui-widgets/src/widgets/textbox.rs @@ -121,13 +121,14 @@ pub struct TextBoxWidget { drag: DragState, cosmic_editor: RefCell>>, max_size: Cell, Option)>>, + text_changed: Cell, scale_factor: Cell>, } pub struct TextBoxResponse { pub render_text: RenderText, pub scroll: Option, - pub text: String, + pub text: Option, /// Whether the user pressed "Enter" in this box, only makes sense in inline pub activated: bool, /// Whether the box lost focus @@ -147,6 +148,7 @@ impl Widget for TextBoxWidget { drag: DragState::None, cosmic_editor: RefCell::new(None), max_size: Cell::default(), + text_changed: Cell::default(), scale_factor: Cell::default(), } } @@ -157,37 +159,43 @@ impl Widget for TextBoxWidget { let mut style = self.props.style.clone(); let mut scroll = None; - let text = self.cosmic_editor.borrow().as_ref().and_then(|editor| { + let mut is_empty = false; + + let text = self.cosmic_editor.borrow().as_ref().map(|editor| { editor.with_buffer(|buffer| { scroll = Some(buffer.scroll()); - - if buffer.lines.iter().all(|v| v.text().is_empty()) { - // Dim towards background - style.color = style - .color - .lerp(&self.props.fill.unwrap_or(Color::CLEAR), 0.75); - - None - } else { - Some( - buffer - .lines - .iter() - .map(|v| v.text()) - .collect::>() - .join("\n"), - ) - } + is_empty = buffer.lines.iter().all(|v| v.text().is_empty()); + + buffer + .lines + .iter() + .map(|v| v.text()) + .collect::>() + .join("\n") }) }); + if is_empty { + // Dim towards background + style.color = style + .color + .lerp(&self.props.fill.unwrap_or(Color::CLEAR), 0.75); + } + Self::Response { + scroll, + text: if self.text_changed.take() { + text.clone() + } else { + None + }, render_text: RenderText { - text: text.clone().unwrap_or(self.props.placeholder.clone()), + text: (!is_empty) + .then_some(text) + .flatten() + .unwrap_or(self.props.placeholder.clone()), style, }, - scroll, - text: text.unwrap_or_default(), activated: mem::take(&mut self.activated), lost_focus: mem::take(&mut self.lost_focus), } @@ -232,6 +240,8 @@ impl Widget for TextBoxWidget { } if let Some(new_text) = &self.props.update_text { + self.text_changed.set(true); + editor.with_buffer_mut(|buffer| { buffer.set_text( font_system, @@ -498,7 +508,6 @@ impl Widget for TextBoxWidget { cosmic_text::Action::Motion(cosmic_text::Motion::PageUp), ); } - EventResponse::Sink } @@ -509,13 +518,13 @@ impl Widget for TextBoxWidget { cosmic_text::Action::Motion(cosmic_text::Motion::PageDown), ); } - EventResponse::Sink } KeyCode::Backspace => { if *down { editor.action(font_system, cosmic_text::Action::Backspace); + self.text_changed.set(true); } EventResponse::Sink } @@ -523,6 +532,7 @@ impl Widget for TextBoxWidget { KeyCode::Delete => { if *down { editor.action(font_system, cosmic_text::Action::Delete); + self.text_changed.set(true); } EventResponse::Sink } @@ -552,12 +562,14 @@ impl Widget for TextBoxWidget { if self.props.inline_edit { if self.props.multiline && modifiers.shift() { editor.action(font_system, cosmic_text::Action::Enter); + self.text_changed.set(true); } else { self.activated = true; ctx.input.set_selection(None); } } else { editor.action(font_system, cosmic_text::Action::Enter); + self.text_changed.set(true); } } EventResponse::Sink @@ -566,7 +578,9 @@ impl Widget for TextBoxWidget { KeyCode::Escape => { if *down { editor.action(font_system, cosmic_text::Action::Escape); - ctx.input.set_selection(None); + if self.props.inline_edit { + ctx.input.set_selection(None); + } } EventResponse::Sink } @@ -591,6 +605,7 @@ impl Widget for TextBoxWidget { } } else { editor.action(font_system, cosmic_text::Action::Insert(*c)); + self.text_changed.set(true); } } }); diff --git a/crates/yakui/examples/autofocus.rs b/crates/yakui/examples/autofocus.rs index d85a6ac9..f36872f8 100644 --- a/crates/yakui/examples/autofocus.rs +++ b/crates/yakui/examples/autofocus.rs @@ -18,7 +18,9 @@ pub fn run() { response.request_focus(); } - text.set(response.into_inner().text); + if let Some(new_text) = response.into_inner().text { + text.set(new_text); + } }); } diff --git a/crates/yakui/examples/clear_textbox.rs b/crates/yakui/examples/clear_textbox.rs index b9e51a3e..ed162543 100644 --- a/crates/yakui/examples/clear_textbox.rs +++ b/crates/yakui/examples/clear_textbox.rs @@ -7,7 +7,9 @@ fn run() { let res = textbox("Hello", if clear.get() { Some("") } else { None }); clear.set(false); - text.set(res.into_inner().text); + if let Some(new_text) = res.into_inner().text { + text.set(new_text); + } if button("Clear").clicked { clear.set(true); diff --git a/crates/yakui/examples/inputs.rs b/crates/yakui/examples/inputs.rs index 68295219..eaa67168 100644 --- a/crates/yakui/examples/inputs.rs +++ b/crates/yakui/examples/inputs.rs @@ -19,7 +19,9 @@ pub fn run() { checked.set(res.checked); let res = textbox("Hello", None); - name.set(res.into_inner().text); + if let Some(new_text) = res.into_inner().text { + name.set(new_text); + } row(|| { if let Some(new_step_size) = slider(step_size.get(), 0.0, 1.0).value { diff --git a/crates/yakui/examples/panels.rs b/crates/yakui/examples/panels.rs index 0fd6c50c..295ce690 100644 --- a/crates/yakui/examples/panels.rs +++ b/crates/yakui/examples/panels.rs @@ -35,7 +35,9 @@ pub fn run() { let name = use_state(|| String::new()); let res = textbox("Hello", None); - name.set(res.into_inner().text); + if let Some(new_text) = res.into_inner().text { + name.set(new_text); + } }); }); diff --git a/crates/yakui/examples/textbox.rs b/crates/yakui/examples/textbox.rs index 56169f5d..c32b6dee 100644 --- a/crates/yakui/examples/textbox.rs +++ b/crates/yakui/examples/textbox.rs @@ -11,7 +11,9 @@ pub fn run() { my_box.placeholder = "placeholder".into(); let response = my_box.show().into_inner(); - text.set(response.text); + if let Some(new_text) = response.text { + text.set(new_text); + } if response.activated { println!("{}", text.borrow()); }