|
|
@ -1,18 +1,17 @@ |
|
|
|
mod confirm; |
|
|
|
mod confirm; |
|
|
|
mod main_wnd; |
|
|
|
mod main_wnd; |
|
|
|
|
|
|
|
use async_channel::Sender; |
|
|
|
pub use confirm::{confirm_wnd, ConfirmWnd}; |
|
|
|
pub use confirm::{confirm_wnd, ConfirmWnd}; |
|
|
|
use crossbeam::channel::Sender; |
|
|
|
|
|
|
|
pub use main_wnd::MainWnd; |
|
|
|
pub use main_wnd::MainWnd; |
|
|
|
|
|
|
|
|
|
|
|
use crate::tui::{ |
|
|
|
use crate::tui::{ |
|
|
|
get_terminal, impls::Id, teardown, utils::Channel, Backend, Frame, GEvent, RetVal, ReturnValue, |
|
|
|
get_terminal, impls::Id, AsyncChannel, Backend, Frame, GEvent, RetVal, ReturnValue, |
|
|
|
GENERAL_EVENT_CHANNEL, |
|
|
|
GENERAL_EVENT_CHANNEL, |
|
|
|
}; |
|
|
|
}; |
|
|
|
use anyhow::Result as AResult; |
|
|
|
use anyhow::Result as AResult; |
|
|
|
use crossterm::event::KeyCode; |
|
|
|
use crossterm::event::KeyCode; |
|
|
|
use once_cell::sync::{Lazy, OnceCell}; |
|
|
|
use once_cell::sync::{Lazy, OnceCell}; |
|
|
|
use std::collections::BTreeMap; |
|
|
|
use std::collections::BTreeMap; |
|
|
|
use std::process::exit; |
|
|
|
|
|
|
|
use std::sync::Arc; |
|
|
|
use std::sync::Arc; |
|
|
|
use std::sync::{Mutex as StdMutex, MutexGuard as StdMutexGuard}; |
|
|
|
use std::sync::{Mutex as StdMutex, MutexGuard as StdMutexGuard}; |
|
|
|
use tokio::sync::{Mutex, MutexGuard}; |
|
|
|
use tokio::sync::{Mutex, MutexGuard}; |
|
|
@ -24,11 +23,10 @@ static WINDOWS: Lazy<Arc<Mutex<WindowsHandler>>> = |
|
|
|
|
|
|
|
|
|
|
|
static LAST_WND_ID: OnceCell<StdMutex<WndId>> = OnceCell::new(); |
|
|
|
static LAST_WND_ID: OnceCell<StdMutex<WndId>> = OnceCell::new(); |
|
|
|
|
|
|
|
|
|
|
|
static WND_EVENT_CHANNEL: Lazy<Channel<WndEvent>> = Lazy::new(|| Channel::new()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub type SharedWnd = Arc<Mutex<dyn Window>>; |
|
|
|
pub type SharedWnd = Arc<Mutex<dyn Window>>; |
|
|
|
|
|
|
|
|
|
|
|
enum WndEvent { |
|
|
|
#[derive(Clone, Debug)] |
|
|
|
|
|
|
|
pub enum WndEvent { |
|
|
|
Key(KeyCode), |
|
|
|
Key(KeyCode), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -36,7 +34,7 @@ enum WndEvent { |
|
|
|
pub struct WndId(u64); |
|
|
|
pub struct WndId(u64); |
|
|
|
|
|
|
|
|
|
|
|
impl WndId { |
|
|
|
impl WndId { |
|
|
|
pub fn last_wid() -> StdMutexGuard<'static, WndId> { |
|
|
|
fn last_wid() -> StdMutexGuard<'static, WndId> { |
|
|
|
LAST_WND_ID |
|
|
|
LAST_WND_ID |
|
|
|
.get_or_init(|| StdMutex::new(WndId(0))) |
|
|
|
.get_or_init(|| StdMutex::new(WndId(0))) |
|
|
|
.lock() |
|
|
|
.lock() |
|
|
@ -54,25 +52,25 @@ impl Default for WndId { |
|
|
|
|
|
|
|
|
|
|
|
#[async_trait] |
|
|
|
#[async_trait] |
|
|
|
pub trait Window: Id<WndId> + RetVal + Send { |
|
|
|
pub trait Window: Id<WndId> + RetVal + Send { |
|
|
|
async fn check_wnd_events(&mut self) { |
|
|
|
async fn handle_event(&mut self, ev: WndEvent) { |
|
|
|
if !WND_EVENT_CHANNEL.is_empty() { |
|
|
|
match ev { |
|
|
|
match WND_EVENT_CHANNEL.recv() { |
|
|
|
WndEvent::Key(k) => { |
|
|
|
WndEvent::Key(k) => { |
|
|
|
self.handle_kbd(k).await.unwrap(); |
|
|
|
self.handle_kbd(k).await.unwrap(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async fn close(&mut self, force: bool) { |
|
|
|
async fn close(&mut self, force: bool) { |
|
|
|
let rv = self.retval(); |
|
|
|
let rv = self.retval(); |
|
|
|
ReturnValue::set(rv).await; |
|
|
|
ReturnValue::set(rv); |
|
|
|
GENERAL_EVENT_CHANNEL.send(GEvent::CloseWnd { |
|
|
|
GENERAL_EVENT_CHANNEL.send(GEvent::CloseWnd { |
|
|
|
wid: self.id(), |
|
|
|
wid: self.id(), |
|
|
|
force, |
|
|
|
force, |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn get_chan(&self) -> &'static AsyncChannel<WndEvent>; |
|
|
|
|
|
|
|
|
|
|
|
fn into_shared(self) -> SharedWnd |
|
|
|
fn into_shared(self) -> SharedWnd |
|
|
|
where |
|
|
|
where |
|
|
|
Self: Sized + 'static, |
|
|
|
Self: Sized + 'static, |
|
|
@ -90,30 +88,35 @@ pub trait Window: Id<WndId> + RetVal + Send { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub struct WndLoop { |
|
|
|
pub struct WndLoop { |
|
|
|
upd_tx: Sender<()>, |
|
|
|
upd_tx: Sender<WndEvent>, |
|
|
|
updater: JoinHandle<()>, |
|
|
|
updater: JoinHandle<()>, |
|
|
|
window: SharedWnd, |
|
|
|
window: SharedWnd, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl WndLoop { |
|
|
|
impl WndLoop { |
|
|
|
pub fn with_wnd(window: SharedWnd) -> Self { |
|
|
|
pub async fn with_wnd(window: SharedWnd) -> Self { |
|
|
|
let Channel { tx, rx } = Channel::new(); |
|
|
|
|
|
|
|
let wnd = window.clone(); |
|
|
|
let wnd = window.clone(); |
|
|
|
|
|
|
|
let AsyncChannel { tx, rx } = wnd.lock().await.get_chan(); |
|
|
|
let wnd_loop = async move { |
|
|
|
let wnd_loop = async move { |
|
|
|
loop { |
|
|
|
loop { |
|
|
|
rx.recv().unwrap(); |
|
|
|
match rx.recv().await { |
|
|
|
wnd.lock().await.check_wnd_events().await; |
|
|
|
Ok(ev) => wnd.lock().await.handle_event(ev).await, |
|
|
|
|
|
|
|
Err(_) => break, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
WndLoop { |
|
|
|
WndLoop { |
|
|
|
upd_tx: tx, |
|
|
|
upd_tx: tx.clone(), |
|
|
|
window, |
|
|
|
window, |
|
|
|
updater: task::spawn(wnd_loop), |
|
|
|
updater: task::spawn(wnd_loop), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn send_update(&self) { |
|
|
|
pub async fn send(&self, ev: WndEvent) { |
|
|
|
self.upd_tx.send(()).unwrap(); |
|
|
|
let wnd_id = self.window.lock().await.id(); |
|
|
|
|
|
|
|
let event = ev.clone(); |
|
|
|
|
|
|
|
debug!(?event, ?wnd_id, "sending"); |
|
|
|
|
|
|
|
self.upd_tx.send(ev).await.expect("big zhopa"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -151,7 +154,8 @@ impl WindowsHandler { |
|
|
|
|
|
|
|
|
|
|
|
pub async fn push_dyn(&mut self, window: SharedWnd) -> SharedWnd { |
|
|
|
pub async fn push_dyn(&mut self, window: SharedWnd) -> SharedWnd { |
|
|
|
let wid = window.lock().await.id(); |
|
|
|
let wid = window.lock().await.id(); |
|
|
|
self.queue.insert(wid, WndLoop::with_wnd(window.clone())); |
|
|
|
self.queue |
|
|
|
|
|
|
|
.insert(wid, WndLoop::with_wnd(window.clone()).await); |
|
|
|
window |
|
|
|
window |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -160,19 +164,12 @@ impl WindowsHandler { |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn show_cursor(&mut self) -> AResult<()> { |
|
|
|
|
|
|
|
self.term.show_cursor()?; |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn draw(&mut self) -> AResult<()> { |
|
|
|
pub async fn draw(&mut self) -> AResult<()> { |
|
|
|
let wids_to_redraw = if self.redraw_all { |
|
|
|
let wids_to_redraw = if self.redraw_all { |
|
|
|
self.redraw_all = false; |
|
|
|
self.redraw_all = false; |
|
|
|
let mut wids = self.queue.keys().cloned().collect::<Vec<WndId>>(); |
|
|
|
self.queue.keys().collect::<Vec<&WndId>>() |
|
|
|
wids.sort(); |
|
|
|
|
|
|
|
wids |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
vec![*WndId::last_wid()] |
|
|
|
vec![self.queue.keys().last().unwrap()] |
|
|
|
}; |
|
|
|
}; |
|
|
|
for wid in wids_to_redraw { |
|
|
|
for wid in wids_to_redraw { |
|
|
|
let mut wnd_locked = match self.queue.get(&wid) { |
|
|
|
let mut wnd_locked = match self.queue.get(&wid) { |
|
|
@ -202,19 +199,17 @@ impl WindowsHandler { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if self.queue.is_empty() { |
|
|
|
if self.queue.is_empty() { |
|
|
|
self.show_cursor().unwrap(); |
|
|
|
GENERAL_EVENT_CHANNEL.send(GEvent::Exit); |
|
|
|
teardown().unwrap(); |
|
|
|
|
|
|
|
exit(0); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn send_handle_kbd(&self, k: KeyCode) { |
|
|
|
pub async fn send_handle_kbd(&self, k: KeyCode) { |
|
|
|
WND_EVENT_CHANNEL.send(WndEvent::Key(k)); |
|
|
|
let current_wnd = self.get_last_wnd(); |
|
|
|
|
|
|
|
current_wnd.send(WndEvent::Key(k)).await; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub async fn update(&mut self) -> AResult<()> { |
|
|
|
pub async fn update(&mut self) -> AResult<()> { |
|
|
|
let current_wnd = self.get_last_wnd(); |
|
|
|
let current_wnd = self.get_last_wnd(); |
|
|
|
current_wnd.send_update(); |
|
|
|
|
|
|
|
current_wnd.window.lock().await.handle_update().await?; |
|
|
|
current_wnd.window.lock().await.handle_update().await?; |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|