improved event loop, added some query shit

This commit is contained in:
emilis 2023-01-25 14:46:11 +00:00
parent dafd1493fe
commit 70168f9ed2
3 changed files with 146 additions and 74 deletions

View File

@ -119,7 +119,7 @@ impl PlanState {
} }
fn render(&mut self, scr: &mut Screen) -> Result<()> { 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 let Some(last) = self.last_render {
if last.elapsed().as_millis() < RENDER_COOLDOWN { if last.elapsed().as_millis() < RENDER_COOLDOWN {
return Ok(()); return Ok(());
@ -132,6 +132,7 @@ impl PlanState {
clear = clear::All, clear = clear::All,
goto = cursor::Goto(1, 1) goto = cursor::Goto(1, 1)
)?; )?;
eprintln!("im rendeeeeeering");
for layer in (&self.layers).into_iter().map(|layer| { for layer in (&self.layers).into_iter().map(|layer| {
let mut line = 1; let mut line = 1;
(&layer.components) (&layer.components)
@ -159,6 +160,42 @@ impl PlanState {
self.last_render = Some(Instant::now()); self.last_render = Some(Instant::now());
Ok(()) Ok(())
} }
fn act_on(
self,
action: Action,
scr: &mut Screen,
) -> Result<Self> {
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<V>(view: V) -> Result<()> pub async fn run<V>(view: V) -> Result<()>
@ -178,15 +215,68 @@ where
let mut plans = let mut plans =
PlanState::from_plans(view.init()?, base_colorset)?; PlanState::from_plans(view.init()?, base_colorset)?;
plans.render(&mut screen)?; plans.render(&mut screen)?;
let mut skip_resize = false;
loop { 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() { 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 => { None => {
std::thread::sleep(Duration::from_millis(1)); std::thread::sleep(Duration::from_millis(1));
continue; continue;
} }
}?; };
// if let termion::event::Event::Mouse(m) = &event { // if let termion::event::Event::Mouse(m) = &event {
// match m { // match m {
// MouseEvent::Press(btn, x, y) => { // MouseEvent::Press(btn, x, y) => {
@ -198,62 +288,9 @@ where
// eprintln!("got event {:#?}", &event); // 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 { if let Some(event) = event {
let (_, update) = view.update(event)?; plans = plans.act_on(view.update(event)?, &mut screen)?;
if let Some(layers) = update {
plans = PlanState::from_plans(layers, base_colorset)?;
} }
} else if !skip_resize {
plans = plans.resized()?;
}
plans.render(&mut screen)?;
skip_resize = false;
} }
Ok(()) Ok(())
} }
@ -308,6 +345,13 @@ impl Layer {
// Simple type alias to be clear that the plans are going to // Simple type alias to be clear that the plans are going to
// be layered on top of eachother // be layered on top of eachother
pub type PlanLayers = Vec<Plan>; pub type PlanLayers = Vec<Plan>;
pub enum Action {
ReplaceAll(PlanLayers),
ReplaceLayer(Plan, usize),
PushLayer(Plan),
PopLayer,
Nothing,
}
pub trait View { pub trait View {
type Message; type Message;
@ -315,11 +359,14 @@ pub trait View {
fn init( fn init(
&mut self, &mut self,
) -> std::result::Result<PlanLayers, anyhow::Error>; ) -> std::result::Result<PlanLayers, anyhow::Error>;
// 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<Self::Message>;
fn update( fn update(
&mut self, &mut self,
event: Event, event: Event<Self::Message>,
) -> std::result::Result< ) -> std::result::Result<Action, anyhow::Error>;
(Self::Message, Option<PlanLayers>),
anyhow::Error,
>;
} }

View File

@ -1,5 +1,6 @@
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Event { pub enum Event<T> {
Link(String), Link(String),
Input(termion::event::Event), Input(termion::event::Event),
Message(T),
} }

View File

@ -1,24 +1,37 @@
use std::time::Duration;
use kkdisp::{ use kkdisp::{
component::{Plan, Widget}, component::{Plan, Widget},
theme::Color, theme::Color,
token::Token, token::Token,
view::Event, view::Event,
View, Action, View,
}; };
use tokio::sync::mpsc::{self, Receiver};
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
kkdisp::run(App::default()).await.unwrap() kkdisp::run(App::default()).await.unwrap();
std::process::exit(0);
} }
pub struct App { pub struct App {
states: Vec<Plan>, states: Vec<Plan>,
index: usize, index: usize,
recv: Receiver<Token>,
} }
impl Default for App { impl Default for App {
fn default() -> Self { 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 { Self {
recv,
index: 0, index: 0,
states: vec![ states: vec![
Plan::start().fill(vec![]).fixed( Plan::start().fill(vec![]).fixed(
@ -58,28 +71,39 @@ impl Default for App {
} }
impl View for App { impl View for App {
type Message = (); type Message = Token;
fn init( fn init(
&mut self, &mut self,
) -> std::result::Result<kkdisp::PlanLayers, anyhow::Error> { ) -> std::result::Result<kkdisp::PlanLayers, anyhow::Error> {
tokio::spawn(async { loop {} });
Ok(vec![self.states[self.index].clone()]) Ok(vec![self.states[self.index].clone()])
} }
fn update( fn update(
&mut self, &mut self,
event: Event, event: Event<Self::Message>,
) -> std::result::Result< ) -> std::result::Result<Action, anyhow::Error> {
(Self::Message, Option<kkdisp::PlanLayers>),
anyhow::Error,
> {
match event { match event {
Event::Link(lnk) => { Event::Link(lnk) => {
eprintln!("recieved link: {}", lnk); eprintln!("recieved link: {}", lnk);
self.index ^= 1; 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<Self::Message> {
match self.recv.try_recv() {
Ok(msg) => Some(msg),
Err(_) => None,
} }
} }
} }