diff --git a/cove-tui/src/ui.rs b/cove-tui/src/ui.rs index 2aa262c..ac68068 100644 --- a/cove-tui/src/ui.rs +++ b/cove-tui/src/ui.rs @@ -15,6 +15,7 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; use tokio::sync::Mutex; use tui::backend::CrosstermBackend; use tui::layout::{Constraint, Direction, Layout}; +use tui::widgets::Paragraph; use tui::{Frame, Terminal}; use crate::room::Room; @@ -92,9 +93,9 @@ impl Ui { // Do a little dance to please the borrow checker let cursor = frame.cursor(); drop(frame); - terminal.set_cursor_opt(cursor)?; terminal.flush()?; + terminal.set_cursor_opt(cursor)?; // Must happen after flush terminal.flush_backend()?; terminal.swap_buffers(); @@ -136,7 +137,10 @@ impl Ui { match reaction { OverlayReaction::Handled => {} OverlayReaction::Close => self.overlay = None, - OverlayReaction::JoinRoom(name) => todo!(), + OverlayReaction::JoinRoom(name) => { + self.overlay = None; + // TODO Join room + } } } return CONTINUE; @@ -197,7 +201,9 @@ impl Ui { if let Some(overlay) = &mut self.overlay { match overlay { Overlay::JoinRoom(state) => { - frame.render_stateful_widget(JoinRoom, entire_area, state) + frame.render_stateful_widget(JoinRoom, entire_area, state); + let (x, y) = state.last_cursor_pos(); + frame.set_cursor(x, y); } } } diff --git a/cove-tui/src/ui/overlays/join_room.rs b/cove-tui/src/ui/overlays/join_room.rs index e7ab91b..95c1c13 100644 --- a/cove-tui/src/ui/overlays/join_room.rs +++ b/cove-tui/src/ui/overlays/join_room.rs @@ -44,3 +44,9 @@ impl EventHandler for JoinRoomState { }) } } + +impl JoinRoomState { + pub fn last_cursor_pos(&self) -> (u16, u16) { + self.room.last_cursor_pos() + } +} diff --git a/cove-tui/src/ui/textline.rs b/cove-tui/src/ui/textline.rs index 673074e..a024b99 100644 --- a/cove-tui/src/ui/textline.rs +++ b/cove-tui/src/ui/textline.rs @@ -18,7 +18,12 @@ impl StatefulWidget for TextLine { fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { Paragraph::new(&state.content as &str).render(area, buf); - // Paragraph::new("foo").render(area, buf); + + // Determine cursor position + let prefix = state.content.chars().take(state.cursor).collect::(); + let position = prefix.width() as u16; + let x = area.x + position.min(area.width); + state.last_cursor_pos = (x, area.y); } } @@ -27,6 +32,7 @@ impl StatefulWidget for TextLine { pub struct TextLineState { content: String, cursor: usize, + last_cursor_pos: (u16, u16), } impl TextLineState { @@ -34,12 +40,9 @@ impl TextLineState { self.content.clone() } - /// Set a frame's cursor position to this text line's cursor position - pub fn set_cursor(&self, f: &mut Frame, area: Rect) { - let prefix = self.content.chars().take(self.cursor).collect::(); - let position = prefix.width() as u16; - let x = area.x + cmp::min(position, area.width); - f.set_cursor(x, area.y); + /// The cursor's position from when the widget was last rendered. + pub fn last_cursor_pos(&self) -> (u16, u16) { + self.last_cursor_pos } fn chars(&self) -> usize {