diff --git a/src/demos/mod.rs b/src/demos/mod.rs index 410cde4..6ee1b5d 100644 --- a/src/demos/mod.rs +++ b/src/demos/mod.rs @@ -16,10 +16,14 @@ pub fn app(screen: Arc) -> Rsx { rsx! { @Handler::new({ let screen = screen.clone(); - move |_, _: &crossterm::event::Event| { - screen.close(); - }}); - FlexRow, gap: 1, { + move |_, e: &crossterm::event::Event| { + if let crossterm::event::Event::Key(crossterm::event::KeyEvent { code, .. }) = e { + if *code == crossterm::event::KeyCode::Char('q') { + screen.close(); + } + } + }}); + FlexRow { FlexCol, gap: 3, { Heading, smooth: false, { "OSUI" } @Transform::new().padding(2, 2); @@ -37,11 +41,16 @@ pub fn app(screen: Arc) -> Rsx { // TODO: div with width full } - FlexCol { + FlexCol, gap: 2, { + @transform!{ y: Center }; static Div { // static only affects the element, not children %count "This will increment every second: {count}" } + + @Transform::new().padding(1, 1).dimensions(40, 1); + @Style { foreground: Some(0xffffff), background: Background::RoundedOutline(0xff0000) }; + Input { } } } } diff --git a/src/elements/input.rs b/src/elements/input.rs new file mode 100644 index 0000000..f89efc5 --- /dev/null +++ b/src/elements/input.rs @@ -0,0 +1,73 @@ +use crossterm::event::{KeyCode, KeyEvent}; + +use crate::{ + state::{use_state, State}, + widget::Element, +}; + +pub struct Input { + pub state: State, + cursor: usize, +} + +impl Element for Input { + fn render(&mut self, scope: &mut crate::prelude::RenderScope) { + let s = self.state.get(); + scope.draw_text(0, 0, &s); + if let Some(c) = s.chars().nth(self.cursor) { + scope.draw_text_inverted(self.cursor as u16, 0, &c.to_string()); + } else { + scope.draw_text_inverted(s.len() as u16, 0, " "); + } + } + + fn event(&mut self, event: &dyn crate::prelude::Event) { + if let Some(crossterm::event::Event::Key(KeyEvent { code, .. })) = event.get() { + match code { + KeyCode::Char(c) => { + self.state.get().insert(self.cursor, *c); + self.cursor += 1; + } + KeyCode::Backspace => { + if self.cursor > 0 { + self.state.get().remove(self.cursor - 1); + self.cursor -= 1; + } + } + KeyCode::Delete => { + if self.cursor > 0 && self.state.get().len() > self.cursor { + self.state.get().remove(self.cursor); + } + } + KeyCode::Left => { + if self.cursor > 0 { + self.cursor -= 1; + } + } + KeyCode::Right => { + if self.cursor < self.state.get().len() { + self.cursor += 1; + } + } + _ => {} + } + } + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} + +impl Input { + pub fn new() -> Self { + Self { + state: use_state(String::new()), + cursor: 0, + } + } +}