Implement TextView::draw

This commit is contained in:
Alexandre Bury 2015-05-15 15:00:20 -07:00
parent 6fad4aa36a
commit 90ea4af1ea
4 changed files with 105 additions and 3 deletions

View File

@ -36,7 +36,9 @@ mod div;
use std::rc::Rc; use std::rc::Rc;
use std::collections::HashMap; use std::collections::HashMap;
use vec2::Vec2;
use view::View; use view::View;
use printer::Printer;
use stack_view::StackView; use stack_view::StackView;
use event::{EventResult,Callback}; use event::{EventResult,Callback};
@ -120,6 +122,7 @@ impl Cursive {
self.screen_mut().add_layer(view); self.screen_mut().add_layer(view);
} }
// Handles a key event when it was ignored by the current view
fn on_key_event(&mut self, ch: i32) { fn on_key_event(&mut self, ch: i32) {
let cb = match self.global_callbacks.get(&ch) { let cb = match self.global_callbacks.get(&ch) {
None => return, None => return,
@ -128,16 +131,48 @@ impl Cursive {
cb(self); cb(self);
} }
pub fn screen_size(&self) -> Vec2 {
let mut x: i32 = 0;
let mut y: i32 = 0;
ncurses::getmaxyx(ncurses::stdscr, &mut y, &mut x);
Vec2 {
x: x as u32,
y: y as u32,
}
}
fn layout(&mut self) {
let size = self.screen_size();
self.screen_mut().layout(size);
}
fn draw(&mut self) {
let printer = Printer {
win: ncurses::stdscr,
offset: Vec2::new(0,0),
size: self.screen_size(),
};
self.screen_mut().draw(&printer);
}
/// Runs the event loop. /// Runs the event loop.
/// It will wait for user input (key presses) and trigger callbacks accordingly. /// It will wait for user input (key presses) and trigger callbacks accordingly.
/// Blocks until quit() is called. /// Blocks until quit() is called.
pub fn run(&mut self) { pub fn run(&mut self) {
while self.running { while self.running {
// Do we need to redraw everytime?
// Probably actually.
ncurses::clear();
self.layout();
self.draw();
ncurses::refresh(); ncurses::refresh();
// Handle event // Blocks until the user press a key.
// TODO: Add a timeout?
let ch = ncurses::getch(); let ch = ncurses::getch();
// If the event was ignored, it is our turn to play with it.
match self.screen_mut().on_key_event(ch) { match self.screen_mut().on_key_event(ch) {
EventResult::Ignored => self.on_key_event(ch), EventResult::Ignored => self.on_key_event(ch),
EventResult::Consumed(None) => (), EventResult::Consumed(None) => (),

View File

@ -6,7 +6,15 @@ use cursive::view::TextView;
fn main() { fn main() {
let mut siv = Cursive::new(); let mut siv = Cursive::new();
siv.add_layer(TextView::new("Hello World!")); siv.add_layer(TextView::new("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean semper risus turpis, a blandit magna scelerisque vitae. Etiam urna dui, ullamcorper ornare libero eu, suscipit lacinia justo. Maecenas lobortis elit vel nibh elementum malesuada. Nam erat lorem, efficitur a tortor eget, mattis tempor nunc. Donec vel fringilla ipsum. Nullam consequat lacus nec feugiat consectetur. Etiam a ante aliquam, aliquet metus id, maximus enim. Maecenas lorem diam, gravida vitae varius suscipit, posuere nec nisl. Nunc non justo est. Ut sagittis est efficitur sapien mollis varius. Sed blandit magna in nibh pellentesque tincidunt. In arcu sem, egestas at odio vel, condimentum placerat lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla venenatis leo eu tellus consectetur tristique. Vestibulum pretium rutrum purus vitae rhoncus. Fusce eros libero, dignissim tristique lobortis et, tincidunt eu ex.
Quisque in bibendum nisi. Donec venenatis ligula dolor, sed malesuada ex tincidunt a. Vestibulum diam nulla, placerat a nibh non, dignissim mollis tortor. Donec lacinia tellus vel nulla mollis accumsan. Suspendisse vel massa vestibulum, aliquet tellus in, dignissim massa. Praesent feugiat viverra cursus. Maecenas eget urna leo. Nullam dui eros, egestas nec lacus vitae, ultrices vestibulum augue. Morbi vel massa eget lorem elementum dignissim eget sed risus. Curabitur ultricies nisl in erat pulvinar maximus. Donec at enim augue. Curabitur lacinia vestibulum risus, eget vulputate ante rhoncus quis.
Praesent iaculis enim id eros consectetur venenatis. Nunc malesuada faucibus luctus. Proin vel malesuada lacus, sed tempus risus. Quisque sagittis arcu dignissim ex pulvinar euismod. Vivamus elementum quis nibh sed rhoncus. Curabitur tristique elit id dolor rhoncus, et facilisis eros dictum. In a vulputate sapien, vitae tincidunt leo. Integer ornare enim elit, a pellentesque ex venenatis at. Pellentesque purus libero, posuere vel magna nec, imperdiet aliquam mi.
Sed consectetur imperdiet augue et consectetur. Aliquam rhoncus nisl et mi lobortis ultricies. Fusce pretium mi nibh, in maximus nunc porta et. Morbi maximus elit vel egestas sagittis. Pellentesque egestas vehicula augue. Quisque ornare placerat ante, non vulputate nisl placerat commodo. Nam sit amet eros placerat, varius diam a, bibendum sem. Mauris orci leo, dapibus nec sapien eu, finibus hendrerit erat. Duis et neque diam. Vivamus nec ultrices ipsum. In hac habitasse platea dictumst. Fusce vel eros sit amet velit sollicitudin eleifend vitae et nunc.
Donec elementum pharetra elit, quis finibus ante dictum et. Vivamus tristique dignissim nulla. Ut dignissim tincidunt elementum. Nullam pellentesque turpis sapien, iaculis sagittis arcu mollis nec. Pellentesque quis vehicula urna. Aenean pretium eget ex vitae interdum. Phasellus pharetra magna id vehicula cursus. Vivamus egestas id nulla et lacinia. Donec congue at eros volutpat tristique. Donec mi tortor, commodo a nisl sed, vulputate malesuada velit. Morbi sed sagittis odio. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia auctor dapibus. Quisque sagittis odio vel urna laoreet ultrices."));
// We can quit by pressing q // We can quit by pressing q
siv.add_global_callback('q' as i32, |s| s.quit()); siv.add_global_callback('q' as i32, |s| s.quit());

View File

@ -46,9 +46,62 @@ impl TextView {
} }
} }
struct LinesIterator<'a> {
line: &'a str,
start: usize,
width: usize,
}
impl <'a> LinesIterator<'a> {
fn new(line: &'a str, width: usize) -> Self {
if line.len() == 0 {
LinesIterator {
line: " ",
width: width,
start: 0,
}
} else {
LinesIterator {
line: line,
width: width,
start: 0,
}
}
}
}
impl <'a> Iterator for LinesIterator<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
if self.start >= self.line.len() {
None
} else if self.start + self.width >= self.line.len() {
let start = self.start;
self.start = self.line.len();
Some(&self.line[start..])
} else {
let start = self.start;
let end = match self.line[start..start+self.width].rfind(" ") {
// Hard break
None => start + self.width,
Some(i) => start+i,
};
self.start = end;
Some(&self.line[start..end])
}
}
}
impl View for TextView { impl View for TextView {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
printer.print((0,0), &self.content); let lines = self.content.split("\n")
.flat_map(|line| LinesIterator::new(line, printer.size.x as usize));
for (i, line) in lines.enumerate() {
printer.print((0,i), line);
}
} }
fn get_min_size(&self, size: SizeRequest) -> Vec2 { fn get_min_size(&self, size: SizeRequest) -> Vec2 {

View File

@ -47,6 +47,12 @@ impl ToVec2 for (u32,u32) {
} }
} }
impl ToVec2 for (usize,usize) {
fn to_vec2(self) -> Vec2 {
Vec2::new(self.0 as u32, self.1 as u32)
}
}
impl Add for Vec2 { impl Add for Vec2 {
type Output = Vec2; type Output = Vec2;