From 70168f9ed2babe233e1d808d162ed81f43875a31 Mon Sep 17 00:00:00 2001 From: emilis Date: Wed, 25 Jan 2023 14:46:11 +0000 Subject: [PATCH] improved event loop, added some query shit --- kkdisp/src/lib.rs | 173 ++++++++++++++++++++++++++++----------------- kkdisp/src/view.rs | 3 +- kkx/src/main.rs | 44 +++++++++--- 3 files changed, 146 insertions(+), 74 deletions(-) diff --git a/kkdisp/src/lib.rs b/kkdisp/src/lib.rs index eae9e70..d27a861 100644 --- a/kkdisp/src/lib.rs +++ b/kkdisp/src/lib.rs @@ -119,7 +119,7 @@ impl PlanState { } fn render(&mut self, scr: &mut Screen) -> Result<()> { - const RENDER_COOLDOWN: u128 = 1000 / 50; + const RENDER_COOLDOWN: u128 = 1000 / 60; if let Some(last) = self.last_render { if last.elapsed().as_millis() < RENDER_COOLDOWN { return Ok(()); @@ -132,6 +132,7 @@ impl PlanState { clear = clear::All, goto = cursor::Goto(1, 1) )?; + eprintln!("im rendeeeeeering"); for layer in (&self.layers).into_iter().map(|layer| { let mut line = 1; (&layer.components) @@ -159,6 +160,42 @@ impl PlanState { self.last_render = Some(Instant::now()); Ok(()) } + + fn act_on( + self, + action: Action, + scr: &mut Screen, + ) -> Result { + let mut new = match action { + Action::ReplaceAll(layers) => { + Self::from_plans(layers, self.base_colorset)? + } + Action::ReplaceLayer(layer, index) => { + if index >= self.plans.len() { + return Err(anyhow::anyhow!( + "cannot replace layer at index {}, have: {}", + index, + self.plans.len() + )); + } else { + todo!() + } + } + Action::PushLayer(layer) => { + let mut layers = self.plans; + layers.push(layer); + Self::from_plans(layers, self.base_colorset)? + } + Action::PopLayer => { + let mut layers = self.plans; + layers.pop(); + Self::from_plans(layers, self.base_colorset)? + } + Action::Nothing => return Ok(self), + }; + new.render(scr)?; + Ok(new) + } } pub async fn run(view: V) -> Result<()> @@ -178,15 +215,68 @@ where let mut plans = PlanState::from_plans(view.init()?, base_colorset)?; plans.render(&mut screen)?; - let mut skip_resize = false; loop { + if let Some(msg) = view.query() { + plans = plans.act_on( + view.update(Event::Message(msg))?, + &mut screen, + )?; + continue; + } let event = match events_iter.next() { - Some(e) => e, + Some(e) => { + let e = e?; + match e { + termion::event::Event::Mouse(mus) => match mus { + MouseEvent::Press(press, x, y) => match press + { + MouseButton::WheelUp => { + plans = plans.scroll_up()?; + plans.render(&mut screen)?; + None + } + MouseButton::WheelDown => { + plans = plans.scroll_down()?; + plans.render(&mut screen)?; + None + } + _ => match plans.match_click((x, y)) { + Some(name) => Some(Event::Link(name)), + None => None, + }, + }, + // Not doing release/whatever mouse events rn + _ => None, + }, + termion::event::Event::Key(key) => { + if let Key::Ctrl(c) = key { + if c == 'c' { + match last_ctrlc { + Some(last) => { + if last.elapsed().as_millis() + < 300 + { + break; + } + } + None => {} + }; + last_ctrlc = Some(Instant::now()); + continue; + } + Some(Event::Input(e)) + } else { + Some(Event::Input(e)) + } + } + _ => Some(Event::Input(e)), + } + } None => { std::thread::sleep(Duration::from_millis(1)); continue; } - }?; + }; // if let termion::event::Event::Mouse(m) = &event { // match m { // MouseEvent::Press(btn, x, y) => { @@ -198,62 +288,9 @@ where // eprintln!("got event {:#?}", &event); // } - let event = match event { - termion::event::Event::Mouse(mus) => match mus { - MouseEvent::Press(press, x, y) => match press { - MouseButton::WheelUp => { - plans = plans.scroll_up()?; - skip_resize = true; - None - } - MouseButton::WheelDown => { - plans = plans.scroll_down()?; - skip_resize = true; - None - } - _ => match plans.match_click((x, y)) { - Some(name) => Some(Event::Link(name)), - None => { - skip_resize = true; - None - } - }, - }, - // Not doing release/whatever mouse events rn - _ => None, - }, - termion::event::Event::Key(key) => { - if let Key::Ctrl(c) = key { - if c == 'c' { - match last_ctrlc { - Some(last) => { - if last.elapsed().as_millis() < 300 { - break; - } - } - None => {} - }; - last_ctrlc = Some(Instant::now()); - continue; - } - Some(Event::Input(event)) - } else { - Some(Event::Input(event)) - } - } - _ => Some(Event::Input(event)), - }; - if let Some(event) = event { - let (_, update) = view.update(event)?; - if let Some(layers) = update { - plans = PlanState::from_plans(layers, base_colorset)?; - } - } else if !skip_resize { - plans = plans.resized()?; + plans = plans.act_on(view.update(event)?, &mut screen)?; } - plans.render(&mut screen)?; - skip_resize = false; } Ok(()) } @@ -308,6 +345,13 @@ impl Layer { // Simple type alias to be clear that the plans are going to // be layered on top of eachother pub type PlanLayers = Vec; +pub enum Action { + ReplaceAll(PlanLayers), + ReplaceLayer(Plan, usize), + PushLayer(Plan), + PopLayer, + Nothing, +} pub trait View { type Message; @@ -315,11 +359,14 @@ pub trait View { fn init( &mut self, ) -> std::result::Result; + + // query is called at the beginning of every loop, and should + // return quickly. Ideally, it should simply return a message + // from some sort of queue, or None if there's an empty queue. + fn query(&mut self) -> Option; + fn update( &mut self, - event: Event, - ) -> std::result::Result< - (Self::Message, Option), - anyhow::Error, - >; + event: Event, + ) -> std::result::Result; } diff --git a/kkdisp/src/view.rs b/kkdisp/src/view.rs index 201b8af..d43fc96 100644 --- a/kkdisp/src/view.rs +++ b/kkdisp/src/view.rs @@ -1,5 +1,6 @@ #[derive(Clone, Debug)] -pub enum Event { +pub enum Event { Link(String), Input(termion::event::Event), + Message(T), } diff --git a/kkx/src/main.rs b/kkx/src/main.rs index 75762dc..891c9a7 100644 --- a/kkx/src/main.rs +++ b/kkx/src/main.rs @@ -1,24 +1,37 @@ +use std::time::Duration; + use kkdisp::{ component::{Plan, Widget}, theme::Color, token::Token, view::Event, - View, + Action, View, }; +use tokio::sync::mpsc::{self, Receiver}; #[tokio::main] async fn main() { - kkdisp::run(App::default()).await.unwrap() + kkdisp::run(App::default()).await.unwrap(); + std::process::exit(0); } pub struct App { states: Vec, index: usize, + recv: Receiver, } impl Default for App { fn default() -> Self { + let (snd, recv) = mpsc::channel(256); + tokio::spawn(async move { + std::thread::sleep(Duration::from_secs(10)); + snd.send(Token::text("this is an event").centered()) + .await + .unwrap(); + }); Self { + recv, index: 0, states: vec![ Plan::start().fill(vec![]).fixed( @@ -58,28 +71,39 @@ impl Default for App { } impl View for App { - type Message = (); + type Message = Token; fn init( &mut self, ) -> std::result::Result { + tokio::spawn(async { loop {} }); Ok(vec![self.states[self.index].clone()]) } fn update( &mut self, - event: Event, - ) -> std::result::Result< - (Self::Message, Option), - anyhow::Error, - > { + event: Event, + ) -> std::result::Result { match event { Event::Link(lnk) => { eprintln!("recieved link: {}", lnk); self.index ^= 1; - Ok(((), Some(vec![self.states[self.index].clone()]))) + Ok(Action::ReplaceAll(vec![ + self.states[self.index].clone() + ])) } - _ => Ok(((), None)), + Event::Message(tok) => { + Ok(Action::ReplaceAll(vec![Plan::start() + .fixed(3, vec![Widget::new(100, vec![tok])])])) + } + _ => Ok(Action::Nothing), + } + } + + fn query(&mut self) -> Option { + match self.recv.try_recv() { + Ok(msg) => Some(msg), + Err(_) => None, } } }