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
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(()) |
|
}
|
|
|