Add focus and hiding options to editor

This commit is contained in:
Joscha 2022-08-22 17:12:07 +02:00
parent e24a5ee1c4
commit 84930c8c34
3 changed files with 38 additions and 20 deletions

View file

@ -1,35 +1,24 @@
use std::sync::Arc; use std::sync::Arc;
use crossterm::event::KeyCode; use crossterm::event::KeyCode;
use crossterm::style::{ContentStyle, Stylize};
use parking_lot::FairMutex; use parking_lot::FairMutex;
use toss::terminal::Terminal; use toss::terminal::Terminal;
use crate::euph::Room; use crate::euph::Room;
use crate::ui::input::{key, InputEvent, KeyBindingsList, KeyEvent}; use crate::ui::input::{key, InputEvent, KeyBindingsList, KeyEvent};
use crate::ui::util; use crate::ui::util;
use crate::ui::widgets::cursor::Cursor;
use crate::ui::widgets::editor::EditorState; use crate::ui::widgets::editor::EditorState;
use crate::ui::widgets::padding::Padding;
use crate::ui::widgets::popup::Popup; use crate::ui::widgets::popup::Popup;
use crate::ui::widgets::text::Text;
use crate::ui::widgets::BoxedWidget; use crate::ui::widgets::BoxedWidget;
pub fn new() -> EditorState { pub fn new() -> EditorState {
EditorState::new() EditorState::new()
} }
pub fn widget() -> BoxedWidget { pub fn widget(editor: &EditorState) -> BoxedWidget {
Popup::new( Popup::new(editor.widget().hidden())
Padding::new(Cursor::new(Text::new(( .title("Enter password")
"<hidden>", .build()
ContentStyle::default().grey().italic(),
))))
.left(1),
)
.title("Enter password")
.inner_padding(false)
.build()
} }
pub fn list_key_bindings(bindings: &mut KeyBindingsList) { pub fn list_key_bindings(bindings: &mut KeyBindingsList) {

View file

@ -190,7 +190,7 @@ impl EuphRoom {
match &self.state { match &self.state {
State::Normal => {} State::Normal => {}
State::Auth(_) => layers.push(auth::widget()), State::Auth(editor) => layers.push(auth::widget(editor)),
State::Nick(editor) => layers.push(nick::widget(editor)), State::Nick(editor) => layers.push(nick::widget(editor)),
} }

View file

@ -2,6 +2,7 @@ use std::iter;
use std::sync::Arc; use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use crossterm::style::{ContentStyle, Stylize};
use parking_lot::{FairMutex, Mutex}; use parking_lot::{FairMutex, Mutex};
use toss::frame::{Frame, Pos, Size}; use toss::frame::{Frame, Pos, Size};
use toss::styled::Styled; use toss::styled::Styled;
@ -335,6 +336,8 @@ impl EditorState {
state: self.0.clone(), state: self.0.clone(),
text, text,
idx, idx,
focus: true,
hidden: None,
} }
} }
@ -420,6 +423,8 @@ pub struct Editor {
state: Arc<Mutex<InnerEditorState>>, state: Arc<Mutex<InnerEditorState>>,
text: Styled, text: Styled,
idx: usize, idx: usize,
focus: bool,
hidden: Option<Styled>,
} }
impl Editor { impl Editor {
@ -433,6 +438,20 @@ impl Editor {
self self
} }
pub fn focus(mut self, active: bool) -> Self {
self.focus = active;
self
}
pub fn hidden(self) -> Self {
self.hidden_with_placeholder(("<hidden>", ContentStyle::default().grey().italic()))
}
pub fn hidden_with_placeholder<S: Into<Styled>>(mut self, placeholder: S) -> Self {
self.hidden = Some(placeholder.into());
self
}
fn wrapped_cursor(cursor_idx: usize, break_indices: &[usize]) -> (usize, usize) { fn wrapped_cursor(cursor_idx: usize, break_indices: &[usize]) -> (usize, usize) {
let mut row = 0; let mut row = 0;
let mut line_idx = cursor_idx; let mut line_idx = cursor_idx;
@ -477,15 +496,25 @@ impl Widget for Editor {
} }
async fn render(self: Box<Self>, frame: &mut Frame) { async fn render(self: Box<Self>, frame: &mut Frame) {
if let Some(placeholder) = self.hidden {
frame.write(Pos::ZERO, placeholder);
if self.focus {
frame.set_cursor(Some(Pos::ZERO));
}
return;
}
let width = frame.size().width.max(1); let width = frame.size().width.max(1);
let text_width = (width - 1) as usize; let text_width = (width - 1) as usize;
let indices = wrap(frame, self.text.text(), text_width); let indices = wrap(frame, self.text.text(), text_width);
let lines = self.text.split_at_indices(&indices); let lines = self.text.split_at_indices(&indices);
let (cursor_row, cursor_line_idx) = Self::wrapped_cursor(self.idx, &indices); if self.focus {
let cursor_col = frame.width(lines[cursor_row].text().split_at(cursor_line_idx).0); let (cursor_row, cursor_line_idx) = Self::wrapped_cursor(self.idx, &indices);
let cursor_col = cursor_col.min(text_width); let cursor_col = frame.width(lines[cursor_row].text().split_at(cursor_line_idx).0);
frame.set_cursor(Some(Pos::new(cursor_col as i32, cursor_row as i32))); let cursor_col = cursor_col.min(text_width);
frame.set_cursor(Some(Pos::new(cursor_col as i32, cursor_row as i32)));
}
for (i, line) in lines.into_iter().enumerate() { for (i, line) in lines.into_iter().enumerate() {
frame.write(Pos::new(0, i as i32), line); frame.write(Pos::new(0, i as i32), line);