From 2d31d3d4e2b4c8b498a3f7b44662864da7bccba1 Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 23 Feb 2022 22:32:52 +0100 Subject: [PATCH] Extract rooms widget and state --- cove-tui/src/ui.rs | 40 +++++++++---------- cove-tui/src/ui/rooms.rs | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 cove-tui/src/ui/rooms.rs diff --git a/cove-tui/src/ui.rs b/cove-tui/src/ui.rs index bc9cf13..18e5c83 100644 --- a/cove-tui/src/ui.rs +++ b/cove-tui/src/ui.rs @@ -1,3 +1,5 @@ +mod rooms; + use std::io::Stdout; 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 tui::backend::CrosstermBackend; use tui::layout::{Constraint, Direction, Layout}; -use tui::widgets::{Block, Borders, Paragraph}; +use tui::widgets::Paragraph; use tui::{Frame, Terminal}; +use self::rooms::{Rooms, RoomsState}; + pub type Backend = CrosstermBackend; #[derive(Debug)] @@ -24,8 +28,7 @@ enum EventHandleResult { pub struct Ui { event_tx: UnboundedSender, - rooms_width: u16, - rooms_dragging: bool, + rooms_state: RoomsState, log: Vec, } @@ -33,8 +36,7 @@ impl Ui { fn new(event_tx: UnboundedSender) -> Self { Self { event_tx, - rooms_width: 24, - rooms_dragging: false, + rooms_state: RoomsState::default(), log: vec!["Hello world!".to_string()], } } @@ -130,17 +132,13 @@ impl Ui { } async fn handle_mouse_event(&mut self, event: MouseEvent) -> anyhow::Result { + let rooms_width = event.column + 1; + let over_rooms = self.rooms_state.width() == rooms_width; match event.kind { - MouseEventKind::Down(_) if event.column == self.rooms_width => { - self.rooms_dragging = true; - } - MouseEventKind::Up(_) => { - self.rooms_dragging = false; - } - MouseEventKind::Drag(_) if self.rooms_dragging => { - self.rooms_width = event.column; - } - // MouseEventKind::Moved => todo!(), + MouseEventKind::Moved => self.rooms_state.hover(over_rooms), + MouseEventKind::Down(_) => self.rooms_state.drag(over_rooms), + MouseEventKind::Up(_) => self.rooms_state.drag(false), + MouseEventKind::Drag(_) => self.rooms_state.drag_to(rooms_width), // MouseEventKind::ScrollDown => todo!(), // MouseEventKind::ScrollUp => todo!(), _ => {} @@ -152,23 +150,23 @@ impl Ui { let outer = Layout::default() .direction(Direction::Horizontal) .constraints([ - Constraint::Length(self.rooms_width), - Constraint::Length(1), + Constraint::Length(self.rooms_state.width()), Constraint::Min(0), ]) .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 { - 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[1].height } else { 0 }; frame.render_widget( Paragraph::new(self.log.join("\n")).scroll((scroll, 0)), - outer[2], + outer[1], ); + Ok(()) } } diff --git a/cove-tui/src/ui/rooms.rs b/cove-tui/src/ui/rooms.rs new file mode 100644 index 0000000..f0b1a99 --- /dev/null +++ b/cove-tui/src/ui/rooms.rs @@ -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; + } + } +}