diff --git a/crates/tek_core/src/tui.rs b/crates/tek_core/src/tui.rs index 2fe1912b..e7a2aaf9 100644 --- a/crates/tek_core/src/tui.rs +++ b/crates/tek_core/src/tui.rs @@ -60,66 +60,67 @@ impl Tui { ) -> Usually>> { let backend = CrosstermBackend::new(stdout()); let area = backend.size()?; - let mut engine = Self { + let engine = Self { exited: Arc::new(AtomicBool::new(false)), event: RwLock::new(None), buffer: 0, buffers: [Buffer::empty(area), Buffer::empty(area)], + area: area.xywh(), backend, - area: area.xywh(), }; - engine.setup()?; let engine = Arc::new(RwLock::new(engine)); - let _input_thread = { - let engine = engine.clone(); - let state = state.clone(); - let poll = Duration::from_millis(100); - spawn(move || loop { - if ::crossterm::event::poll(poll).is_ok() { - let event = TuiEvent::Input(::crossterm::event::read().unwrap()); - match event { - key!(Ctrl-KeyCode::Char('c')) => { - engine.write().unwrap().exited.store(true, Ordering::Relaxed); - }, - _ => { - *engine.write().unwrap().event.write().unwrap() = Some(event); - if let Err(e) = state.write().unwrap().handle(&*engine.read().unwrap()) { - panic!("{e}") - } + let _input_thread = Self::spawn_input_thread(&engine, &state, Duration::from_millis(100)); + engine.write().unwrap().setup()?; + let render_thread = Self::spawn_render_thread(&engine, &state, Duration::from_millis(20)); + render_thread.join().expect("main thread failed"); + engine.write().unwrap().teardown()?; + Ok(state) + } + fn spawn_input_thread + Sized + 'static> ( + engine: &Arc>, state: &Arc>, poll: Duration + ) -> JoinHandle<()> { + let exited = engine.read().unwrap().exited.clone(); + let engine = engine.clone(); + let state = state.clone(); + spawn(move || loop { + if exited.fetch_and(true, Ordering::Relaxed) { + break + } + if ::crossterm::event::poll(poll).is_ok() { + let event = TuiEvent::Input(::crossterm::event::read().unwrap()); + match event { + key!(Ctrl-KeyCode::Char('c')) => { + engine.write().unwrap().exited.store(true, Ordering::Relaxed); + }, + _ => { + *engine.write().unwrap().event.write().unwrap() = Some(event); + if let Err(e) = state.write().unwrap().handle(&*engine.read().unwrap()) { + panic!("{e}") } } } - if engine.read().unwrap().exited() { - break - } - //engine.read().unwrap().handle(&mut *state.write().unwrap()).expect("handle failed"); - }) - }; - let main_thread = { - let engine = engine.clone(); - let state = state.clone(); - let sleep = Duration::from_millis(20); - spawn(move || loop { - let size = { - let engine = engine.read().unwrap(); - if engine.exited() { - break - } - engine.backend.size().expect("get size failed").xywh() - }; - { - let mut engine = engine.write().unwrap(); - engine.area = size; - state.read().unwrap().render(&mut engine).expect("render failed"); - engine.flip(); - std::mem::drop(engine); - } - std::thread::sleep(sleep); - }) - }; - main_thread.join().expect("main thread failed"); - engine.write().unwrap().teardown()?; - Ok(state) + } + //engine.read().unwrap().handle(&mut *state.write().unwrap()).expect("handle failed"); + }) + } + fn spawn_render_thread + Sized + 'static> ( + engine: &Arc>, state: &Arc>, sleep: Duration + ) -> JoinHandle<()> { + let exited = engine.read().unwrap().exited.clone(); + let engine = engine.clone(); + let state = state.clone(); + spawn(move || loop { + if exited.fetch_and(true, Ordering::Relaxed) { + break + } + if let Ok(state) = state.try_read() { + let mut engine = engine.write().unwrap(); + engine.area = engine.backend.size().expect("get size failed").xywh(); + state.render(&mut engine).expect("render failed"); + engine.flip(); + } + std::thread::sleep(sleep); + }) } pub fn event (&self) -> TuiEvent { self.event.read().unwrap().clone().unwrap()