Add focus and hiding options to editor
This commit is contained in:
parent
e24a5ee1c4
commit
84930c8c34
3 changed files with 38 additions and 20 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue