Forráskód Böngészése

Merge pull request #9 from Demonthos/master

Finished InputHandler
Jonathan Kelley 3 éve
szülő
commit
04afce7992
4 módosított fájl, 88 hozzáadás és 57 törlés
  1. 28 19
      examples/keys.rs
  2. 53 36
      src/hooks.rs
  3. 4 1
      src/lib.rs
  4. 3 1
      src/render.rs

+ 28 - 19
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,6 +9,9 @@ fn main() {
 }
 
 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! {
@@ -18,25 +21,31 @@ fn app(cx: Scope) -> Element {
             background_color: "red",
             justify_content: "center",
             align_items: "center",
-            "Hello world!",
+            flex_direction: "column",
 
-            // 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| {
+                    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);
+                },
+                onmousedown: move |evt: MouseEvent| {
+                    set_mouse((evt.row, evt.column));
+                },
+                onresize: move |dims| {
+                    set_size(dims);
+                },
+            },
+            "count: {count:?}",
+            "key: {key:?}",
+            "mouse: {mouse:?}",
+            "resize: {size:?}",
         }
     })
 }

+ 53 - 36
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<Option<TermEvent>>,
-    receiver: Rc<Cell<Option<UnboundedReceiver<TermEvent>>>>,
+    last_event: Rc<Cell<Option<TermEvent>>>,
+    subscribers: Rc<RefCell<HashMap<ScopeId, bool>>>,
 }
 
 impl RinkContext {
-    pub fn new(receiver: UnboundedReceiver<TermEvent>) -> Self {
+    pub fn new(mut receiver: UnboundedReceiver<TermEvent>, 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<TermEvent> {
+        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<EventHandler<'a, (u16, u16)>>,
+    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));
+                }
             }
         }
     }

+ 4 - 1
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();

+ 3 - 1
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();