Render entire UI using widgets
This commit is contained in:
parent
8b3166c6d7
commit
3bbe52b797
2 changed files with 28 additions and 20 deletions
35
src/ui.rs
35
src/ui.rs
|
|
@ -14,7 +14,6 @@ use parking_lot::FairMutex;
|
||||||
use tokio::sync::mpsc::error::TryRecvError;
|
use tokio::sync::mpsc::error::TryRecvError;
|
||||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use toss::frame::Frame;
|
|
||||||
use toss::terminal::Terminal;
|
use toss::terminal::Terminal;
|
||||||
|
|
||||||
use crate::logger::{LogMsg, Logger};
|
use crate::logger::{LogMsg, Logger};
|
||||||
|
|
@ -22,7 +21,7 @@ use crate::vault::Vault;
|
||||||
|
|
||||||
use self::chat::ChatState;
|
use self::chat::ChatState;
|
||||||
use self::rooms::Rooms;
|
use self::rooms::Rooms;
|
||||||
use self::widgets::Widget;
|
use self::widgets::BoxedWidget;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UiEvent {
|
pub enum UiEvent {
|
||||||
|
|
@ -121,26 +120,32 @@ impl Ui {
|
||||||
mut event_rx: UnboundedReceiver<UiEvent>,
|
mut event_rx: UnboundedReceiver<UiEvent>,
|
||||||
crossterm_lock: Arc<FairMutex<()>>,
|
crossterm_lock: Arc<FairMutex<()>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
loop {
|
// Initial render so we don't show a blank screen until the first event
|
||||||
// 1. Render current state
|
terminal.autoresize()?;
|
||||||
terminal.autoresize()?;
|
terminal.frame().reset();
|
||||||
self.render(terminal.frame()).await?;
|
self.widget().await.render(terminal.frame()).await;
|
||||||
terminal.present()?;
|
terminal.present()?;
|
||||||
|
|
||||||
// 2. Measure widths if required
|
loop {
|
||||||
|
// 1. Measure grapheme widths if required
|
||||||
if terminal.measuring_required() {
|
if terminal.measuring_required() {
|
||||||
let _guard = crossterm_lock.lock();
|
let _guard = crossterm_lock.lock();
|
||||||
terminal.measure_widths()?;
|
terminal.measure_widths()?;
|
||||||
self.event_tx.send(UiEvent::Redraw)?;
|
self.event_tx.send(UiEvent::Redraw)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Handle events (in batches)
|
// 2. Handle events (in batches)
|
||||||
let mut event = match event_rx.recv().await {
|
let mut event = match event_rx.recv().await {
|
||||||
Some(event) => event,
|
Some(event) => event,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
terminal.autoresize()?;
|
terminal.autoresize()?;
|
||||||
loop {
|
loop {
|
||||||
|
// Render in-between events so the next event is handled in an
|
||||||
|
// up-to-date state. The results of these intermediate renders
|
||||||
|
// will be thrown away before the final render.
|
||||||
|
self.widget().await.render(terminal.frame()).await;
|
||||||
|
|
||||||
let result = match event {
|
let result = match event {
|
||||||
UiEvent::Redraw => EventHandleResult::Continue,
|
UiEvent::Redraw => EventHandleResult::Continue,
|
||||||
UiEvent::Term(Event::Key(event)) => {
|
UiEvent::Term(Event::Key(event)) => {
|
||||||
|
|
@ -160,15 +165,19 @@ impl Ui {
|
||||||
Err(TryRecvError::Disconnected) => return Ok(()),
|
Err(TryRecvError::Disconnected) => return Ok(()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Render and present final state
|
||||||
|
terminal.frame().reset();
|
||||||
|
self.widget().await.render(terminal.frame()).await;
|
||||||
|
terminal.present()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render(&mut self, frame: &mut Frame) -> anyhow::Result<()> {
|
async fn widget(&mut self) -> BoxedWidget {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::Main => self.rooms.render(frame).await,
|
Mode::Main => self.rooms.widget().await,
|
||||||
Mode::Log => Box::new(self.log_chat.widget()).render(frame).await,
|
Mode::Log => self.log_chat.widget().into(),
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_key_event(
|
async fn handle_key_event(
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ use crossterm::event::{KeyCode, KeyEvent};
|
||||||
use crossterm::style::{ContentStyle, Stylize};
|
use crossterm::style::{ContentStyle, Stylize};
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use toss::frame::Frame;
|
|
||||||
use toss::styled::Styled;
|
use toss::styled::Styled;
|
||||||
use toss::terminal::Terminal;
|
use toss::terminal::Terminal;
|
||||||
|
|
||||||
|
|
@ -18,7 +17,7 @@ use super::room::EuphRoom;
|
||||||
use super::widgets::background::Background;
|
use super::widgets::background::Background;
|
||||||
use super::widgets::list::{List, ListState};
|
use super::widgets::list::{List, ListState};
|
||||||
use super::widgets::text::Text;
|
use super::widgets::text::Text;
|
||||||
use super::widgets::Widget;
|
use super::widgets::BoxedWidget;
|
||||||
use super::{util, UiEvent};
|
use super::{util, UiEvent};
|
||||||
|
|
||||||
pub struct Rooms {
|
pub struct Rooms {
|
||||||
|
|
@ -67,14 +66,14 @@ impl Rooms {
|
||||||
rooms
|
rooms
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn render(&mut self, frame: &mut Frame) {
|
pub async fn widget(&mut self) -> BoxedWidget {
|
||||||
if let Some(room) = &self.focus {
|
if let Some(room) = &self.focus {
|
||||||
let actual_room = self.euph_rooms.entry(room.clone()).or_insert_with(|| {
|
let actual_room = self.euph_rooms.entry(room.clone()).or_insert_with(|| {
|
||||||
EuphRoom::new(self.vault.euph(room.clone()), self.ui_event_tx.clone())
|
EuphRoom::new(self.vault.euph(room.clone()), self.ui_event_tx.clone())
|
||||||
});
|
});
|
||||||
actual_room.widget().await.render(frame).await;
|
actual_room.widget().await
|
||||||
} else {
|
} else {
|
||||||
self.render_rooms(frame).await;
|
self.rooms_widget().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,11 +147,11 @@ impl Rooms {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render_rooms(&mut self, frame: &mut Frame) {
|
async fn rooms_widget(&mut self) -> BoxedWidget {
|
||||||
let rooms = self.stabilize_rooms().await;
|
let rooms = self.stabilize_rooms().await;
|
||||||
let mut list = self.list.list().focus(true);
|
let mut list = self.list.list().focus(true);
|
||||||
self.render_rows(&mut list, rooms).await;
|
self.render_rows(&mut list, rooms).await;
|
||||||
Box::new(list).render(frame).await;
|
list.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_key_event(
|
pub async fn handle_key_event(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue