From 3f739d351b631992c8dfc8f38ad594bbb0b6637e Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 4 Feb 2022 14:52:01 -0600 Subject: [PATCH 1/3] finished InputHandler --- examples/keys.rs | 40 +++++++++++----------- src/hooks.rs | 89 ++++++++++++++++++++++++++++-------------------- src/lib.rs | 5 ++- src/render.rs | 4 ++- 4 files changed, 81 insertions(+), 57 deletions(-) diff --git a/examples/keys.rs b/examples/keys.rs index 1270c5ea7..be9319126 100644 --- a/examples/keys.rs +++ b/examples/keys.rs @@ -9,7 +9,9 @@ fn main() { } fn app(cx: Scope) -> Element { - let (count, set_count) = use_state(&cx, || 0); + let (key, set_key) = use_state(&cx, || "".to_string()); + let (mouse, set_mouse) = use_state(&cx, || "".to_string()); + let (size, set_size) = use_state(&cx, || "".to_string()); cx.render(rsx! { div { @@ -18,25 +20,25 @@ fn app(cx: Scope) -> Element { background_color: "red", justify_content: "center", align_items: "center", - "Hello world!", - // todo: enabling this will panic - // rink::InputHandler { - // onkeydown: move |evt: KeyEvent| { - // use crossterm::event::KeyCode::*; - // match evt.code { - // Left => set_count(count + 1), - // Right => set_count(count - 1), - // Up => set_count(count + 10), - // Down => set_count(count - 10), - // _ => {}, - // } - // }, - // onmousedown: move |evt| {}, - // onresize: move |dims| { - // println!("{:?}", dims); - // }, - // } + rink::InputHandler { + onkeydown: move |evt: KeyEvent| { + set_key(format!("{evt:?}")); + }, + }, + rink::InputHandler { + onmousedown: move |evt| { + set_mouse(format!("{evt:?}")); + }, + }, + rink::InputHandler { + onresize: move |dims| { + set_size(format!("{dims:?}")); + }, + }, + "keyboard: {key} + mouse: {mouse} + resize: {size}", } }) } diff --git a/src/hooks.rs b/src/hooks.rs index 045325761..9ec8d47a6 100644 --- a/src/hooks.rs +++ b/src/hooks.rs @@ -17,22 +17,51 @@ use std::{ time::{Duration, Instant}, }; use stretch2::{prelude::Size, Stretch}; +use tokio::sync::broadcast::Receiver; use tui::{backend::CrosstermBackend, style::Style as TuiStyle, Terminal}; pub struct RinkContext { - last_event: RefCell>, - receiver: Rc>>>, + last_event: Rc>>, + subscribers: Rc>>, } impl RinkContext { - pub fn new(receiver: UnboundedReceiver) -> Self { + pub fn new(mut receiver: UnboundedReceiver, cx: &ScopeState) -> Self { + let updater = cx.schedule_update_any(); + let last_event = Rc::new(Cell::new(None)); + let last_event2 = last_event.clone(); + let subscribers = Rc::new(RefCell::new(HashMap::new())); + let subscribers2 = subscribers.clone(); + + cx.push_future(async move { + while let Some(evt) = receiver.next().await { + last_event2.replace(Some(evt)); + for (subscriber, received) in subscribers2.borrow_mut().iter_mut() { + updater(*subscriber); + *received = false; + } + } + }); + Self { - last_event: RefCell::new(None), - receiver: Rc::new(Cell::new(Some(receiver))), + last_event: last_event, + subscribers: subscribers, } } + pub fn subscribe_to_events(&self, scope: ScopeId) { - // + self.subscribers.borrow_mut().insert(scope, false); + } + + pub fn get_event(&self, scope: ScopeId) -> Option { + let mut subscribers = self.subscribers.borrow_mut(); + let received = subscribers.get_mut(&scope)?; + if !*received { + *received = true; + self.last_event.get() + } else { + None + } } } @@ -45,7 +74,7 @@ pub struct AppHandlerProps<'a> { onmousedown: EventHandler<'a, MouseEvent>, #[props(default)] - onresize: Option>, + onresize: EventHandler<'a, (u16, u16)>, } /// This component lets you handle input events @@ -64,38 +93,26 @@ pub fn InputHandler<'a>(cx: Scope<'a, AppHandlerProps<'a>>) -> Element { // perhaps add some tracking to context? rcx.subscribe_to_events(cx.scope_id()); - let mut rec = rcx.receiver.take().unwrap(); - let updater = cx.schedule_update(); - let rc2 = rcx.clone(); - cx.push_future(async move { - while let Some(evt) = rec.next().await { - rc2.last_event.borrow_mut().replace(evt); - println!("{:?}", evt); - updater(); - } - // - }); - rcx }); - if let Some(evet) = rcx.last_event.borrow().as_ref() { - match evet { - TermEvent::Key(key) => { - cx.props.onkeydown.call(key.clone()); - // let mut handler = cx.props.keydown.borrow_mut(); - // handler(*key); - // if let Some(handler) = cx.props.onkeydown { - // handler(*key); - // } - } - TermEvent::Mouse(mouse) => { - cx.props.onmousedown.call(mouse.clone()); - } - TermEvent::Resize(x, y) => { - // if let Some(handler) = cx.props.onresize { - // handler((*x, *y)); - // } + { + if let Some(evet) = rcx.get_event(cx.scope_id()) { + match evet { + TermEvent::Key(key) => { + cx.props.onkeydown.call(key.clone()); + // let mut handler = cx.props.keydown.borrow_mut(); + // handler(*key); + // if let Some(handler) = cx.props.onkeydown { + // handler(*key); + // } + } + TermEvent::Mouse(mouse) => { + cx.props.onmousedown.call(mouse.clone()); + } + TermEvent::Resize(x, y) => { + cx.props.onresize.call((x, y)); + } } } } diff --git a/src/lib.rs b/src/lib.rs index 801d5e068..89206b934 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,10 @@ pub fn launch(app: Component<()>) { let mut dom = VirtualDom::new(app); let (tx, rx) = unbounded(); - dom.base_scope().provide_context(RinkContext::new(rx)); + let cx = dom.base_scope(); + + cx.provide_root_context(RinkContext::new(rx, cx)); + dom.rebuild(); render_vdom(&mut dom, tx).unwrap(); diff --git a/src/render.rs b/src/render.rs index 9189e4eaa..21cc6e01f 100644 --- a/src/render.rs +++ b/src/render.rs @@ -53,7 +53,9 @@ pub fn render_vnode<'a>( return; } - VNode::Placeholder(_) | VNode::Element(_) | VNode::Text(_) => {} + VNode::Placeholder(_) => return, + + VNode::Element(_) | VNode::Text(_) => {} } let id = node.try_mounted_id().unwrap(); From 981c3689330e58bd731ebaa3298a85d18167d38f Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 4 Feb 2022 15:03:55 -0600 Subject: [PATCH 2/3] reformated and center aligned example --- examples/keys.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/keys.rs b/examples/keys.rs index be9319126..e30f13bdb 100644 --- a/examples/keys.rs +++ b/examples/keys.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; -use crossterm::event::KeyEvent; +use crossterm::event::{KeyCode, KeyEvent, MouseEvent}; use dioxus::prelude::*; use rink::InputHandler; @@ -9,9 +9,9 @@ fn main() { } fn app(cx: Scope) -> Element { - let (key, set_key) = use_state(&cx, || "".to_string()); - let (mouse, set_mouse) = use_state(&cx, || "".to_string()); - let (size, set_size) = use_state(&cx, || "".to_string()); + let (key, set_key) = use_state(&cx, || KeyCode::Null); + let (mouse, set_mouse) = use_state(&cx, || (0, 0)); + let (size, set_size) = use_state(&cx, || (0, 0)); cx.render(rsx! { div { @@ -20,25 +20,26 @@ fn app(cx: Scope) -> Element { background_color: "red", justify_content: "center", align_items: "center", + flex_direction: "column", rink::InputHandler { onkeydown: move |evt: KeyEvent| { - set_key(format!("{evt:?}")); + set_key(evt.code); }, }, rink::InputHandler { - onmousedown: move |evt| { - set_mouse(format!("{evt:?}")); + onmousedown: move |evt: MouseEvent| { + set_mouse((evt.row, evt.column)); }, }, rink::InputHandler { onresize: move |dims| { - set_size(format!("{dims:?}")); + set_size(dims); }, }, - "keyboard: {key} - mouse: {mouse} - resize: {size}", + "keyboard: {key:?}", + "mouse: {mouse:?}", + "resize: {size:?}", } }) } From be535c558c3bbb4d63f874783118e878c6311a9a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 4 Feb 2022 15:09:26 -0600 Subject: [PATCH 3/3] combined input handlers --- examples/keys.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/keys.rs b/examples/keys.rs index e30f13bdb..ef9df9750 100644 --- a/examples/keys.rs +++ b/examples/keys.rs @@ -12,6 +12,7 @@ fn app(cx: Scope) -> Element { let (key, set_key) = use_state(&cx, || KeyCode::Null); let (mouse, set_mouse) = use_state(&cx, || (0, 0)); let (size, set_size) = use_state(&cx, || (0, 0)); + let (count, set_count) = use_state(&cx, || 0); cx.render(rsx! { div { @@ -24,20 +25,25 @@ fn app(cx: Scope) -> Element { rink::InputHandler { onkeydown: move |evt: KeyEvent| { + use crossterm::event::KeyCode::*; + match evt.code { + Left => set_count(count + 1), + Right => set_count(count - 1), + Up => set_count(count + 10), + Down => set_count(count - 10), + _ => {}, + } set_key(evt.code); }, - }, - rink::InputHandler { onmousedown: move |evt: MouseEvent| { set_mouse((evt.row, evt.column)); }, - }, - rink::InputHandler { onresize: move |dims| { set_size(dims); }, }, - "keyboard: {key:?}", + "count: {count:?}", + "key: {key:?}", "mouse: {mouse:?}", "resize: {size:?}", }