You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.8 KiB

mod impls;
mod retval;
mod utils;
mod windows;
use anyhow::Result as AResult;
use backtrace::Backtrace;
use crossterm::event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode};
use crossterm::execute;
use crossterm::terminal::{
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
};
use once_cell::sync::Lazy;
use retval::{RetVal, ReturnValue};
use std::panic::set_hook;
use std::process::exit;
use std::{
io::{stdout, Stdout},
thread,
time::Duration,
};
use tui::{backend::CrosstermBackend, Terminal};
use utils::Channel;
use windows::{MainWnd, SharedWnd, WindowsHandler, WndId};
pub type Backend = CrosstermBackend<Stdout>;
pub type Frame<'f> = tui::Frame<'f, Backend>;
const EVENT_GEN_PERIOD: Duration = Duration::from_millis(120);
static GENERAL_EVENT_CHANNEL: Lazy<Channel<GEvent>> = Lazy::new(|| Channel::new());
enum GEvent {
CreateWnd(SharedWnd),
CloseWnd { wid: WndId, force: bool },
Key(KeyCode),
Tick,
}
fn get_terminal() -> AResult<Terminal<Backend>> {
let backend = CrosstermBackend::new(stdout());
Ok(Terminal::new(backend)?)
}
pub async fn init_tui() -> AResult<()> {
//TODO: fix this
set_hook(Box::new(|p| {
teardown().unwrap();
get_terminal().unwrap().show_cursor().unwrap();
eprintln!("{}\n{:?}", p, Backtrace::new());
exit(254);
}));
if let Err(e) = init().await {
teardown()?;
return Err(e);
}
Ok(())
}
async fn init() -> AResult<()> {
enable_raw_mode()?;
execute!(stdout(), EnterAlternateScreen, EnableMouseCapture)?;
WindowsHandler::lock().await.push_new::<MainWnd>().await;
thread::spawn(move || loop {
if event::poll(EVENT_GEN_PERIOD).unwrap() {
match event::read().unwrap() {
Event::Key(key) => GENERAL_EVENT_CHANNEL.send(GEvent::Key(key.code)),
_ => (),
}
} else {
GENERAL_EVENT_CHANNEL.send(GEvent::Tick)
}
});
WindowsHandler::lock().await.clear()?;
loop {
match GENERAL_EVENT_CHANNEL.recv() {
GEvent::Tick => {
let mut wh = WindowsHandler::lock().await;
wh.update().await?;
wh.draw().await?;
}
GEvent::CloseWnd { wid, force } => {
let mut wh = WindowsHandler::lock().await;
wh.close(wid, force).await;
}
GEvent::Key(key) => {
WindowsHandler::lock().await.send_handle_kbd(key);
}
GEvent::CreateWnd(wnd) => {
WindowsHandler::lock().await.push_dyn(wnd).await;
}
}
}
}
fn teardown() -> AResult<()> {
disable_raw_mode()?;
execute!(stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
Ok(())
}