mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Edit view now support content larger than display
It then scrolls horizontally
This commit is contained in:
parent
fa4b52ee81
commit
af47abeaad
@ -1,16 +1,28 @@
|
|||||||
use ncurses;
|
use ncurses;
|
||||||
|
|
||||||
|
use std::cmp::min;
|
||||||
|
|
||||||
use theme::ColorPair;
|
use theme::ColorPair;
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use view::{View,IdView,SizeRequest};
|
use view::{View,IdView,SizeRequest};
|
||||||
use event::*;
|
use event::*;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
/// Displays an editable text.
|
/// Input box where the user can enter and edit text.
|
||||||
pub struct EditView {
|
pub struct EditView {
|
||||||
|
/// Current content
|
||||||
content: String,
|
content: String,
|
||||||
|
/// Cursor position in the content
|
||||||
cursor: usize,
|
cursor: usize,
|
||||||
|
/// Minimum layout length asked to the parent
|
||||||
min_length: usize,
|
min_length: usize,
|
||||||
|
|
||||||
|
/// When the content is too long for the display, offset it
|
||||||
|
offset: usize,
|
||||||
|
/// Last display length, to know the possible offset range
|
||||||
|
last_length: usize,
|
||||||
|
// scrollable: bool,
|
||||||
|
// TODO: add a max text length?
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditView {
|
impl EditView {
|
||||||
@ -19,12 +31,16 @@ impl EditView {
|
|||||||
EditView {
|
EditView {
|
||||||
content: String::new(),
|
content: String::new(),
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
|
offset: 0,
|
||||||
min_length: 1,
|
min_length: 1,
|
||||||
|
last_length: 0,
|
||||||
|
// scrollable: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace the entire content of the view with the given one.
|
/// Replace the entire content of the view with the given one.
|
||||||
pub fn set_content<'a>(&mut self, content: &'a str) {
|
pub fn set_content<'a>(&mut self, content: &'a str) {
|
||||||
|
self.offset = 0;
|
||||||
self.content = content.to_string();
|
self.content = content.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +83,18 @@ impl View for EditView {
|
|||||||
let len = self.content.chars().count();
|
let len = self.content.chars().count();
|
||||||
printer.with_color(ColorPair::Secondary, |printer| {
|
printer.with_color(ColorPair::Secondary, |printer| {
|
||||||
printer.with_style(ncurses::A_REVERSE(), |printer| {
|
printer.with_style(ncurses::A_REVERSE(), |printer| {
|
||||||
|
if len < self.last_length {
|
||||||
printer.print((0,0), &self.content);
|
printer.print((0,0), &self.content);
|
||||||
printer.print_hline((len,0), printer.size.x-len, '_' as u64);
|
printer.print_hline((len,0), printer.size.x-len, '_' as u64);
|
||||||
|
} else {
|
||||||
|
let visible_end = min(self.content.len(), self.offset + self.last_length);
|
||||||
|
|
||||||
|
let content = &self.content[self.offset..visible_end];
|
||||||
|
printer.print((0,0), content);
|
||||||
|
if visible_end - self.offset < printer.size.x {
|
||||||
|
printer.print((printer.size.x-1,0), "_");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now print cursor
|
// Now print cursor
|
||||||
@ -79,11 +105,15 @@ impl View for EditView {
|
|||||||
// Get the char from the string... Is it so hard?
|
// Get the char from the string... Is it so hard?
|
||||||
self.content.chars().nth(self.cursor).expect(&format!("Found no char at cursor {} in {}", self.cursor, self.content))
|
self.content.chars().nth(self.cursor).expect(&format!("Found no char at cursor {} in {}", self.cursor, self.content))
|
||||||
};
|
};
|
||||||
printer.print_hline((self.cursor, 0), 1, c as u64);
|
printer.print_hline((self.cursor-self.offset, 0), 1, c as u64);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn layout(&mut self, size: Vec2) {
|
||||||
|
self.last_length = size.x;
|
||||||
|
}
|
||||||
|
|
||||||
fn get_min_size(&self, _: SizeRequest) -> Vec2 {
|
fn get_min_size(&self, _: SizeRequest) -> Vec2 {
|
||||||
Vec2::new(self.min_length, 1)
|
Vec2::new(self.min_length, 1)
|
||||||
}
|
}
|
||||||
@ -102,8 +132,8 @@ impl View for EditView {
|
|||||||
None => self.content.push(ch),
|
None => self.content.push(ch),
|
||||||
Some((i,_)) => self.content.insert(i, ch),
|
Some((i,_)) => self.content.insert(i, ch),
|
||||||
}
|
}
|
||||||
|
// TODO: handle wide (CJK) chars
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
return EventResult::Consumed(None);
|
|
||||||
},
|
},
|
||||||
Event::KeyEvent(key) => match key {
|
Event::KeyEvent(key) => match key {
|
||||||
Key::Home => self.cursor = 0,
|
Key::Home => self.cursor = 0,
|
||||||
@ -113,10 +143,26 @@ impl View for EditView {
|
|||||||
Key::Backspace if self.cursor > 0 => { self.cursor -= 1; remove_char(&mut self.content, self.cursor); },
|
Key::Backspace if self.cursor > 0 => { self.cursor -= 1; remove_char(&mut self.content, self.cursor); },
|
||||||
Key::Del if self.cursor < self.content.chars().count() => { remove_char(&mut self.content, self.cursor); },
|
Key::Del if self.cursor < self.content.chars().count() => { remove_char(&mut self.content, self.cursor); },
|
||||||
_ => return EventResult::Ignored,
|
_ => return EventResult::Ignored,
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep cursor in [offset, offset+last_length] by changing offset
|
||||||
|
// So keep offset in [last_length-cursor,cursor]
|
||||||
|
// Also call this on resize, but right now it is an event like any other
|
||||||
|
if self.cursor >= self.offset + self.last_length {
|
||||||
|
self.offset = self.cursor - self.last_length + 1;
|
||||||
|
} else if self.cursor < self.offset {
|
||||||
|
self.offset = self.cursor;
|
||||||
|
}
|
||||||
|
if self.offset + self.last_length > self.content.len() + 1{
|
||||||
|
|
||||||
|
self.offset = if self.content.len() > self.last_length {
|
||||||
|
self.content.len() - self.last_length + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user