Add scroll to textarea
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use crossterm::event::Event;
|
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
||||||
use rat_cursor::HasScreenCursor;
|
use rat_cursor::HasScreenCursor;
|
||||||
use ratatui::buffer::Buffer;
|
use ratatui::buffer::Buffer;
|
||||||
use ratatui::layout::{Constraint, Direction, Layout, Rect};
|
use ratatui::layout::{Constraint, Direction, Layout, Rect};
|
||||||
use ratatui::prelude::StatefulWidget;
|
use ratatui::prelude::StatefulWidget;
|
||||||
use ratatui::style::{Color, Stylize};
|
use ratatui::style::{Color, Stylize};
|
||||||
use ratatui::text::Text;
|
use ratatui::text::{Line, Span, Text};
|
||||||
use ratatui::widgets::{Block, Borders, Paragraph, Widget};
|
use ratatui::widgets::{Block, Borders, Paragraph, Widget};
|
||||||
use tui_input::backend::crossterm::EventHandler;
|
use tui_input::backend::crossterm::EventHandler;
|
||||||
use tui_input::Input;
|
use tui_input::Input;
|
||||||
@@ -16,6 +16,8 @@ pub struct TextArea {
|
|||||||
title: String,
|
title: String,
|
||||||
style: TextAreaStyle,
|
style: TextAreaStyle,
|
||||||
input_area: Option<Rect>,
|
input_area: Option<Rect>,
|
||||||
|
scroll_offset: u16,
|
||||||
|
auto_scroll: bool,
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,14 +43,29 @@ impl StatefulWidget for TextArea {
|
|||||||
} else if matches!(self.style, TextAreaStyle::SingleLine) {
|
} else if matches!(self.style, TextAreaStyle::SingleLine) {
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Percentage(10), Constraint::Fill(0)])
|
.constraints([Constraint::Max((self.title.len() + 1) as u16), Constraint::Fill(0)])
|
||||||
.split(area);
|
.split(area);
|
||||||
let text = Text::from(self.title);
|
let label_text = Text::from(self.title);
|
||||||
let line = Paragraph::new(text);
|
let label = Paragraph::new(label_text);
|
||||||
let input_text = Text::from(input_value).fg(Color::White);
|
|
||||||
let paragraph = Paragraph::new(input_text).bg(Color::Green);
|
// let scroll_offset = if self.input.cursor() > chunks[1].width as usize {
|
||||||
|
// self.input.cursor() - chunks[1].width as usize
|
||||||
|
// } else { 0 };
|
||||||
|
|
||||||
|
let input_text = Span::from(input_value.clone()).fg(Color::White);
|
||||||
|
let input_line = Line::from(input_text);
|
||||||
|
let paragraph = Paragraph::new(input_line)
|
||||||
|
.bg(Color::Green)
|
||||||
|
.scroll((0, self.scroll_offset));
|
||||||
|
|
||||||
|
if self.input_area.is_none() {
|
||||||
state.input_area = Some(chunks[1]);
|
state.input_area = Some(chunks[1]);
|
||||||
line.render(chunks[0], buf);
|
}
|
||||||
|
else if let Some(area) = self.input_area && area != chunks[1] {
|
||||||
|
state.input_area = Some(chunks[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
label.render(chunks[0], buf);
|
||||||
paragraph.render(chunks[1], buf);
|
paragraph.render(chunks[1], buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,26 +77,44 @@ impl HasScreenCursor for TextArea {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let area = self.input_area.unwrap();
|
let area = self.input_area.unwrap();
|
||||||
let width = area.width.max(3) - 3;
|
let scroll = self.input.visual_scroll(1);
|
||||||
let scroll = self.input.visual_scroll(width as usize);
|
let x = self.input.visual_cursor().max(scroll) as u16 - self.scroll_offset;
|
||||||
let x = (self.input.visual_cursor().max(scroll) - scroll) as u16;
|
|
||||||
Some((area.x + x, area.y))
|
Some((area.x + x, area.y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextArea {
|
impl TextArea {
|
||||||
pub fn new(title: &str, placeholder_text: &str, style: Option<TextAreaStyle>) -> Self {
|
pub fn new(title: &str, placeholder_text: &str, style: Option<TextAreaStyle>, auto_scroll: Option<bool>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
input: Input::new(placeholder_text.to_string()),
|
input: Input::new(placeholder_text.to_string()),
|
||||||
title: title.to_string(),
|
title: title.to_string(),
|
||||||
active: false,
|
active: false,
|
||||||
style: style.unwrap_or(TextAreaStyle::SingleLine),
|
style: style.unwrap_or(TextAreaStyle::SingleLine),
|
||||||
input_area: None,
|
input_area: None,
|
||||||
|
auto_scroll: auto_scroll.unwrap_or(true),
|
||||||
|
scroll_offset: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_input(&mut self, event: &Event) -> Result<()> {
|
pub fn handle_input(&mut self, event: &Event) -> Result<()> {
|
||||||
let _ = self.input.handle_event(event);
|
let _ = self.input.handle_event(event);
|
||||||
|
|
||||||
|
if let Event::Key(key) = event &&
|
||||||
|
!matches!(key.kind, KeyEventKind::Release) &&
|
||||||
|
let Some(area) = self.input_area {
|
||||||
|
|
||||||
|
let cursor_pos = self.input.cursor() as u16;
|
||||||
|
if self.scroll_offset > cursor_pos {
|
||||||
|
self.scroll_offset = cursor_pos;
|
||||||
|
} else if cursor_pos >= area.width + self.scroll_offset {
|
||||||
|
self.scroll_offset = cursor_pos - area.width;
|
||||||
|
} else if self.auto_scroll && self.scroll_offset > 0 && (key.code.is_delete() || key.code.is_backspace()) {
|
||||||
|
self.scroll_offset -= 1;
|
||||||
|
// HACK: with_cursor function requires to be owned so use handle event
|
||||||
|
let _ = self.input.handle_event(&Event::Key(KeyEvent::new(KeyCode::Left, KeyModifiers::empty())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub struct AddFolderPopup {
|
|||||||
|
|
||||||
impl AddFolderPopup {
|
impl AddFolderPopup {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut textarea = TextArea::new("Folder Path", "", None);
|
let mut textarea = TextArea::new("Folder Path", "", None, None);
|
||||||
textarea.active = true;
|
textarea.active = true;
|
||||||
Self { textarea }
|
Self { textarea }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user