diff --git a/src/component.rs b/src/component.rs index 40e63c4..5fd828e 100644 --- a/src/component.rs +++ b/src/component.rs @@ -5,6 +5,7 @@ use std::{ }; use crate::{ + engine::CommandExecutor, render::DrawContext, state::{use_effect, HookDependency}, View, ViewWrapper, @@ -22,6 +23,7 @@ pub struct Context { event_handlers: Mutex>>, view: Mutex, pub(crate) scopes: Mutex>>, + // executor: Arc, } impl Context { diff --git a/src/engine/benchmark.rs b/src/engine/benchmark.rs index d3ed0a1..df8c700 100644 --- a/src/engine/benchmark.rs +++ b/src/engine/benchmark.rs @@ -87,4 +87,8 @@ impl Engine for Benchmark { fn render_delay(&self) { self.0.render_delay(); } + + fn executor(&self) -> Arc { + self.0.executor() + } } diff --git a/src/engine/commands.rs b/src/engine/commands.rs new file mode 100644 index 0000000..d93ee1d --- /dev/null +++ b/src/engine/commands.rs @@ -0,0 +1 @@ +pub struct Stop; diff --git a/src/engine/console.rs b/src/engine/console.rs index ddf4d21..bf79937 100644 --- a/src/engine/console.rs +++ b/src/engine/console.rs @@ -5,18 +5,31 @@ use std::{ use crossterm::{cursor::MoveTo, execute, terminal::Clear}; -use crate::{prelude::Context, render::Area, DrawContext, View}; +use crate::{ + engine::{commands, CommandExecutor}, + prelude::Context, + render::Area, + DrawContext, View, +}; use super::Engine; +pub struct ConsoleExecutor { + running: Mutex, +} + pub struct Console { threads: Mutex) + Send + Sync>>>, + executor: Arc, } impl Console { pub fn new() -> Self { Self { threads: Mutex::new(Vec::new()), + executor: Arc::new(ConsoleExecutor { + running: Mutex::new(true), + }), } } @@ -84,4 +97,40 @@ impl Engine for Console { cx } + + fn executor(&self) -> Arc { + self.executor.clone() + } + + fn run) -> View + Send + Sync + 'static>(&self, component: F) { + let cx = self.init(component); + + while self.executor.is_running() { + self.render(&cx); + self.render_delay(); + } + } +} + +impl ConsoleExecutor { + pub fn is_running(self: &Arc) -> bool { + *self.running.lock().unwrap() + } + + pub fn stop(&self) -> crate::Result<()> { + *self.running.lock()? = false; + Ok(()) + } +} + +impl CommandExecutor for ConsoleExecutor { + fn execute_command(&self, command: &Arc) -> crate::Result<()> { + let command = command.as_any(); + + if let Some(commands::Stop) = command.downcast_ref() { + self.stop()?; + } + + Ok(()) + } } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index a228b4d..daf5474 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -1,4 +1,5 @@ pub mod benchmark; +pub mod commands; pub mod console; pub use benchmark::*; @@ -29,6 +30,7 @@ pub trait Engine { fn render_view(&self, area: &Area, view: &View) -> DrawContext; fn draw_context(&self, ctx: &DrawContext); + fn executor(&self) -> Arc; } pub trait Command { diff --git a/src/lib.rs b/src/lib.rs index 3590d5f..b41e0bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,4 +21,12 @@ pub type View = Arc; pub type ViewWrapper = Arc; pub type Result = std::result::Result; -pub enum Error {} +pub enum Error { + PoisonError, +} + +impl From>> for Error { + fn from(_value: std::sync::PoisonError>) -> Self { + Error::PoisonError + } +}