Migrate key bindings list widget to AsyncWidget
This commit is contained in:
parent
d5b6dd9802
commit
adc70ad233
2 changed files with 86 additions and 54 deletions
20
src/ui.rs
20
src/ui.rs
|
|
@ -28,8 +28,8 @@ pub use self::chat::ChatMsg;
|
||||||
use self::chat::ChatState;
|
use self::chat::ChatState;
|
||||||
use self::input::{key, InputEvent, KeyBindingsList};
|
use self::input::{key, InputEvent, KeyBindingsList};
|
||||||
use self::rooms::Rooms;
|
use self::rooms::Rooms;
|
||||||
use self::widgets::list::ListState;
|
|
||||||
use self::widgets::WidgetWrapper;
|
use self::widgets::WidgetWrapper;
|
||||||
|
use self::widgets2::ListState;
|
||||||
|
|
||||||
/// Time to spend batch processing events before redrawing the screen.
|
/// Time to spend batch processing events before redrawing the screen.
|
||||||
const EVENT_PROCESSING_TIME: Duration = Duration::from_millis(1000 / 15); // 15 fps
|
const EVENT_PROCESSING_TIME: Duration = Duration::from_millis(1000 / 15); // 15 fps
|
||||||
|
|
@ -184,6 +184,14 @@ impl Ui {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn widget(&mut self) -> BoxedAsync<'_, UiError> {
|
async fn widget(&mut self) -> BoxedAsync<'_, UiError> {
|
||||||
|
let key_bindings_list = if self.key_bindings_list.is_some() {
|
||||||
|
let mut bindings = KeyBindingsList::new();
|
||||||
|
self.list_key_bindings(&mut bindings).await;
|
||||||
|
Some(bindings)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let widget = match self.mode {
|
let widget = match self.mode {
|
||||||
Mode::Main => WidgetWrapper::new(self.rooms.widget().await).boxed_async(),
|
Mode::Main => WidgetWrapper::new(self.rooms.widget().await).boxed_async(),
|
||||||
Mode::Log => {
|
Mode::Log => {
|
||||||
|
|
@ -191,10 +199,12 @@ impl Ui {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(key_bindings_list) = &self.key_bindings_list {
|
if let Some(key_bindings_list) = key_bindings_list {
|
||||||
let mut bindings = KeyBindingsList::new(key_bindings_list);
|
// We checked whether this was Some earlier.
|
||||||
self.list_key_bindings(&mut bindings).await;
|
let list_state = self.key_bindings_list.as_mut().unwrap();
|
||||||
WidgetWrapper::new(bindings.widget())
|
|
||||||
|
key_bindings_list
|
||||||
|
.widget(list_state)
|
||||||
.above(widget)
|
.above(widget)
|
||||||
.boxed_async()
|
.boxed_async()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
116
src/ui/input.rs
116
src/ui/input.rs
|
|
@ -2,19 +2,11 @@ use std::convert::Infallible;
|
||||||
|
|
||||||
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
||||||
use crossterm::style::Stylize;
|
use crossterm::style::Stylize;
|
||||||
use toss::{Style, Styled};
|
use toss::widgets::{BoxedAsync, Empty, Join2, Text};
|
||||||
|
use toss::{Style, Styled, WidgetExt};
|
||||||
|
|
||||||
use super::widgets::background::Background;
|
use super::widgets2::ListState;
|
||||||
use super::widgets::border::Border;
|
use super::UiError;
|
||||||
use super::widgets::empty::Empty;
|
|
||||||
use super::widgets::float::Float;
|
|
||||||
use super::widgets::join::{HJoin, Segment};
|
|
||||||
use super::widgets::layer::Layer;
|
|
||||||
use super::widgets::list::{List, ListState};
|
|
||||||
use super::widgets::padding::Padding;
|
|
||||||
use super::widgets::resize::Resize;
|
|
||||||
use super::widgets::text::Text;
|
|
||||||
use super::widgets::BoxedWidget;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum InputEvent {
|
pub enum InputEvent {
|
||||||
|
|
@ -83,66 +75,96 @@ macro_rules! key {
|
||||||
}
|
}
|
||||||
pub(crate) use key;
|
pub(crate) use key;
|
||||||
|
|
||||||
/// Helper wrapper around a list widget for a more consistent key binding style.
|
enum Row {
|
||||||
pub struct KeyBindingsList(List<Infallible>);
|
Empty,
|
||||||
|
Heading(String),
|
||||||
|
Binding(String, String),
|
||||||
|
BindingContd(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct KeyBindingsList(Vec<Row>);
|
||||||
|
|
||||||
impl KeyBindingsList {
|
impl KeyBindingsList {
|
||||||
/// Width of the left column of key bindings.
|
/// Width of the left column of key bindings.
|
||||||
const BINDING_WIDTH: u16 = 20;
|
const BINDING_WIDTH: u16 = 20;
|
||||||
|
|
||||||
pub fn new(state: &ListState<Infallible>) -> Self {
|
pub fn new() -> Self {
|
||||||
Self(state.widget())
|
Self(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binding_style() -> Style {
|
fn binding_style() -> Style {
|
||||||
Style::new().cyan()
|
Style::new().cyan()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn widget(self) -> BoxedWidget {
|
fn row_widget(row: Row) -> BoxedAsync<'static, UiError> {
|
||||||
|
match row {
|
||||||
|
Row::Empty => Empty::new().boxed_async(),
|
||||||
|
|
||||||
|
Row::Heading(name) => Text::new((name, Style::new().bold())).boxed_async(),
|
||||||
|
|
||||||
|
Row::Binding(binding, description) => Join2::horizontal(
|
||||||
|
Text::new((binding, Self::binding_style()))
|
||||||
|
.padding()
|
||||||
|
.with_right(1)
|
||||||
|
.resize()
|
||||||
|
.with_min_width(Self::BINDING_WIDTH)
|
||||||
|
.segment(),
|
||||||
|
Text::new(description).segment(),
|
||||||
|
)
|
||||||
|
.boxed_async(),
|
||||||
|
|
||||||
|
Row::BindingContd(description) => Join2::horizontal(
|
||||||
|
Empty::new().with_width(Self::BINDING_WIDTH).segment(),
|
||||||
|
Text::new(description).segment(),
|
||||||
|
)
|
||||||
|
.boxed_async(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn widget(self, list_state: &mut ListState<Infallible>) -> BoxedAsync<'_, UiError> {
|
||||||
let binding_style = Self::binding_style();
|
let binding_style = Self::binding_style();
|
||||||
Float::new(Layer::new(vec![
|
|
||||||
Border::new(Background::new(Padding::new(self.0).horizontal(1))).into(),
|
let hint_text = Styled::new("jk/↓↑", binding_style)
|
||||||
Float::new(
|
|
||||||
Padding::new(Text::new(
|
|
||||||
Styled::new("jk/↓↑", binding_style)
|
|
||||||
.then_plain(" to scroll, ")
|
.then_plain(" to scroll, ")
|
||||||
.then("esc", binding_style)
|
.then("esc", binding_style)
|
||||||
.then_plain(" to close"),
|
.then_plain(" to close");
|
||||||
))
|
|
||||||
.horizontal(1),
|
let hint = Text::new(hint_text)
|
||||||
)
|
.padding()
|
||||||
.horizontal(0.5)
|
.with_horizontal(1)
|
||||||
.into(),
|
.float()
|
||||||
]))
|
.with_horizontal(0.5)
|
||||||
.horizontal(0.5)
|
.with_vertical(0.0);
|
||||||
.vertical(0.5)
|
|
||||||
.into()
|
let mut list = list_state.widget();
|
||||||
|
for row in self.0 {
|
||||||
|
list.add_unsel(Self::row_widget(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
list.padding()
|
||||||
|
.with_horizontal(1)
|
||||||
|
.border()
|
||||||
|
.below(hint)
|
||||||
|
.background()
|
||||||
|
.float()
|
||||||
|
.with_center()
|
||||||
|
.boxed_async()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty(&mut self) {
|
pub fn empty(&mut self) {
|
||||||
self.0.add_unsel(Empty::new());
|
self.0.push(Row::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn heading(&mut self, name: &str) {
|
pub fn heading(&mut self, name: &str) {
|
||||||
self.0.add_unsel(Text::new((name, Style::new().bold())));
|
self.0.push(Row::Heading(name.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binding(&mut self, binding: &str, description: &str) {
|
pub fn binding(&mut self, binding: &str, description: &str) {
|
||||||
let widget = HJoin::new(vec![
|
self.0
|
||||||
Segment::new(
|
.push(Row::Binding(binding.to_string(), description.to_string()));
|
||||||
Resize::new(Padding::new(Text::new((binding, Self::binding_style()))).right(1))
|
|
||||||
.min_width(Self::BINDING_WIDTH),
|
|
||||||
),
|
|
||||||
Segment::new(Text::new(description)),
|
|
||||||
]);
|
|
||||||
self.0.add_unsel(widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binding_ctd(&mut self, description: &str) {
|
pub fn binding_ctd(&mut self, description: &str) {
|
||||||
let widget = HJoin::new(vec![
|
self.0.push(Row::BindingContd(description.to_string()));
|
||||||
Segment::new(Resize::new(Empty::new()).min_width(Self::BINDING_WIDTH)),
|
|
||||||
Segment::new(Text::new(description)),
|
|
||||||
]);
|
|
||||||
self.0.add_unsel(widget);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue