Extract rooms widget and state
This commit is contained in:
parent
980f78f9a7
commit
2d31d3d4e2
2 changed files with 103 additions and 21 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
mod rooms;
|
||||||
|
|
||||||
use std::io::Stdout;
|
use std::io::Stdout;
|
||||||
|
|
||||||
use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, MouseEvent, MouseEventKind};
|
use crossterm::event::{Event, EventStream, KeyCode, KeyEvent, MouseEvent, MouseEventKind};
|
||||||
|
|
@ -6,9 +8,11 @@ use tokio::sync::mpsc::error::TryRecvError;
|
||||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||||
use tui::backend::CrosstermBackend;
|
use tui::backend::CrosstermBackend;
|
||||||
use tui::layout::{Constraint, Direction, Layout};
|
use tui::layout::{Constraint, Direction, Layout};
|
||||||
use tui::widgets::{Block, Borders, Paragraph};
|
use tui::widgets::Paragraph;
|
||||||
use tui::{Frame, Terminal};
|
use tui::{Frame, Terminal};
|
||||||
|
|
||||||
|
use self::rooms::{Rooms, RoomsState};
|
||||||
|
|
||||||
pub type Backend = CrosstermBackend<Stdout>;
|
pub type Backend = CrosstermBackend<Stdout>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -24,8 +28,7 @@ enum EventHandleResult {
|
||||||
|
|
||||||
pub struct Ui {
|
pub struct Ui {
|
||||||
event_tx: UnboundedSender<UiEvent>,
|
event_tx: UnboundedSender<UiEvent>,
|
||||||
rooms_width: u16,
|
rooms_state: RoomsState,
|
||||||
rooms_dragging: bool,
|
|
||||||
log: Vec<String>,
|
log: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,8 +36,7 @@ impl Ui {
|
||||||
fn new(event_tx: UnboundedSender<UiEvent>) -> Self {
|
fn new(event_tx: UnboundedSender<UiEvent>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
event_tx,
|
event_tx,
|
||||||
rooms_width: 24,
|
rooms_state: RoomsState::default(),
|
||||||
rooms_dragging: false,
|
|
||||||
log: vec!["Hello world!".to_string()],
|
log: vec!["Hello world!".to_string()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,17 +132,13 @@ impl Ui {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_mouse_event(&mut self, event: MouseEvent) -> anyhow::Result<EventHandleResult> {
|
async fn handle_mouse_event(&mut self, event: MouseEvent) -> anyhow::Result<EventHandleResult> {
|
||||||
|
let rooms_width = event.column + 1;
|
||||||
|
let over_rooms = self.rooms_state.width() == rooms_width;
|
||||||
match event.kind {
|
match event.kind {
|
||||||
MouseEventKind::Down(_) if event.column == self.rooms_width => {
|
MouseEventKind::Moved => self.rooms_state.hover(over_rooms),
|
||||||
self.rooms_dragging = true;
|
MouseEventKind::Down(_) => self.rooms_state.drag(over_rooms),
|
||||||
}
|
MouseEventKind::Up(_) => self.rooms_state.drag(false),
|
||||||
MouseEventKind::Up(_) => {
|
MouseEventKind::Drag(_) => self.rooms_state.drag_to(rooms_width),
|
||||||
self.rooms_dragging = false;
|
|
||||||
}
|
|
||||||
MouseEventKind::Drag(_) if self.rooms_dragging => {
|
|
||||||
self.rooms_width = event.column;
|
|
||||||
}
|
|
||||||
// MouseEventKind::Moved => todo!(),
|
|
||||||
// MouseEventKind::ScrollDown => todo!(),
|
// MouseEventKind::ScrollDown => todo!(),
|
||||||
// MouseEventKind::ScrollUp => todo!(),
|
// MouseEventKind::ScrollUp => todo!(),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -152,23 +150,23 @@ impl Ui {
|
||||||
let outer = Layout::default()
|
let outer = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([
|
.constraints([
|
||||||
Constraint::Length(self.rooms_width),
|
Constraint::Length(self.rooms_state.width()),
|
||||||
Constraint::Length(1),
|
|
||||||
Constraint::Min(0),
|
Constraint::Min(0),
|
||||||
])
|
])
|
||||||
.split(frame.size());
|
.split(frame.size());
|
||||||
|
|
||||||
frame.render_widget(Block::default().borders(Borders::RIGHT), outer[1]);
|
frame.render_stateful_widget(Rooms::new(), outer[0], &mut self.rooms_state);
|
||||||
|
|
||||||
let scroll = if self.log.len() as u16 > outer[2].height {
|
let scroll = if self.log.len() as u16 > outer[1].height {
|
||||||
self.log.len() as u16 - outer[2].height
|
self.log.len() as u16 - outer[1].height
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(self.log.join("\n")).scroll((scroll, 0)),
|
Paragraph::new(self.log.join("\n")).scroll((scroll, 0)),
|
||||||
outer[2],
|
outer[1],
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
84
cove-tui/src/ui/rooms.rs
Normal file
84
cove-tui/src/ui/rooms.rs
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
|
use tui::buffer::Buffer;
|
||||||
|
use tui::layout::Rect;
|
||||||
|
use tui::style::{Modifier, Style};
|
||||||
|
use tui::widgets::{Block, Borders, StatefulWidget, Widget};
|
||||||
|
|
||||||
|
pub struct Rooms {}
|
||||||
|
|
||||||
|
impl Rooms {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatefulWidget for Rooms {
|
||||||
|
type State = RoomsState;
|
||||||
|
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
state.width = cmp::min(state.width, area.width);
|
||||||
|
|
||||||
|
// let left = Rect {
|
||||||
|
// width: area.width - 1,
|
||||||
|
// ..area
|
||||||
|
// };
|
||||||
|
let right = Rect {
|
||||||
|
x: area.right() - 1,
|
||||||
|
width: 1,
|
||||||
|
..area
|
||||||
|
};
|
||||||
|
let style = if state.hovering {
|
||||||
|
Style::default().add_modifier(Modifier::REVERSED)
|
||||||
|
} else {
|
||||||
|
Style::default()
|
||||||
|
};
|
||||||
|
Block::default()
|
||||||
|
.borders(Borders::RIGHT)
|
||||||
|
.style(style)
|
||||||
|
.render(right, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RoomsState {
|
||||||
|
width: u16,
|
||||||
|
offset: u16,
|
||||||
|
hovering: bool,
|
||||||
|
dragging: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RoomsState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
width: 24,
|
||||||
|
offset: 0,
|
||||||
|
hovering: false,
|
||||||
|
dragging: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoomsState {
|
||||||
|
pub fn width(&self) -> u16 {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hover(&mut self, active: bool) {
|
||||||
|
self.hovering = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drag(&mut self, active: bool) {
|
||||||
|
self.dragging = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dragging(&self) -> bool {
|
||||||
|
self.dragging
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drag_to(&mut self, width: u16) {
|
||||||
|
if self.dragging {
|
||||||
|
self.width = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue