mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
StackView now centers its children
This commit is contained in:
parent
90ea4af1ea
commit
6cd2a28966
10
src/lib.rs
10
src/lib.rs
@ -154,22 +154,27 @@ impl Cursive {
|
|||||||
size: self.screen_size(),
|
size: self.screen_size(),
|
||||||
};
|
};
|
||||||
self.screen_mut().draw(&printer);
|
self.screen_mut().draw(&printer);
|
||||||
|
ncurses::wrefresh(ncurses::stdscr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) {
|
||||||
|
// And the big event loop begins!
|
||||||
while self.running {
|
while self.running {
|
||||||
// Do we need to redraw everytime?
|
// Do we need to redraw everytime?
|
||||||
// Probably actually.
|
// Probably actually.
|
||||||
|
// TODO: Do we actually need to clear everytime?
|
||||||
ncurses::clear();
|
ncurses::clear();
|
||||||
|
// TODO: Do we need to re-layout everytime?
|
||||||
self.layout();
|
self.layout();
|
||||||
|
// TODO: Do we need to redraw every view every time?
|
||||||
|
// (Is this getting repetitive? :p)
|
||||||
self.draw();
|
self.draw();
|
||||||
ncurses::refresh();
|
|
||||||
|
|
||||||
// Blocks until the user press a key.
|
// Blocks until the user press a key.
|
||||||
// TODO: Add a timeout?
|
// TODO: Add a timeout? Animations?
|
||||||
let ch = ncurses::getch();
|
let ch = ncurses::getch();
|
||||||
|
|
||||||
// If the event was ignored, it is our turn to play with it.
|
// If the event was ignored, it is our turn to play with it.
|
||||||
@ -183,7 +188,6 @@ impl Cursive {
|
|||||||
|
|
||||||
pub fn quit(&mut self) {
|
pub fn quit(&mut self) {
|
||||||
self.running = false;
|
self.running = false;
|
||||||
println!("Quitting now!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/main.rs
12
src/main.rs
@ -6,18 +6,10 @@ use cursive::view::TextView;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut siv = Cursive::new();
|
let mut siv = Cursive::new();
|
||||||
|
|
||||||
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());
|
||||||
|
|
||||||
|
siv.add_layer(TextView::new("Hello World!\nPress q to quit the application."));
|
||||||
|
|
||||||
siv.run();
|
siv.run();
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
|
|
||||||
use vec2::Vec2;
|
use vec2::Vec2;
|
||||||
use view::{View,SizeRequest};
|
use view::{View,SizeRequest,DimensionRequest};
|
||||||
use event::EventResult;
|
use event::EventResult;
|
||||||
use printer::Printer;
|
use printer::Printer;
|
||||||
|
|
||||||
/// Simple stack of views.
|
/// Simple stack of views.
|
||||||
/// Only the top-most view is active and can receive input.
|
/// Only the top-most view is active and can receive input.
|
||||||
pub struct StackView {
|
pub struct StackView {
|
||||||
layers: Vec<Box<View>>,
|
layers: Vec<Layer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Layer {
|
||||||
|
view: Box<View>,
|
||||||
|
size: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackView {
|
impl StackView {
|
||||||
@ -21,7 +26,10 @@ impl StackView {
|
|||||||
|
|
||||||
/// Add new view on top of the stack.
|
/// Add new view on top of the stack.
|
||||||
pub fn add_layer<T: 'static + View>(&mut self, view: T) {
|
pub fn add_layer<T: 'static + View>(&mut self, view: T) {
|
||||||
self.layers.push(Box::new(view));
|
self.layers.push(Layer {
|
||||||
|
view: Box::new(view),
|
||||||
|
size: Vec2::new(0,0),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the top-most layer.
|
/// Remove the top-most layer.
|
||||||
@ -35,14 +43,28 @@ impl View for StackView {
|
|||||||
fn draw(&self, printer: &Printer) {
|
fn draw(&self, printer: &Printer) {
|
||||||
match self.layers.last() {
|
match self.layers.last() {
|
||||||
None => (),
|
None => (),
|
||||||
Some(v) => v.draw(printer),
|
Some(v) => {
|
||||||
|
let offset = (printer.size - v.size) / 2;
|
||||||
|
v.view.draw(&printer.sub_printer(offset, v.size));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_key_event(&mut self, ch: i32) -> EventResult {
|
fn on_key_event(&mut self, ch: i32) -> EventResult {
|
||||||
match self.layers.last_mut() {
|
match self.layers.last_mut() {
|
||||||
None => EventResult::Ignored,
|
None => EventResult::Ignored,
|
||||||
Some(v) => v.on_key_event(ch),
|
Some(v) => v.view.on_key_event(ch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout(&mut self, size: Vec2) {
|
||||||
|
let req = SizeRequest {
|
||||||
|
w: DimensionRequest::AtMost(size.x),
|
||||||
|
h: DimensionRequest::AtMost(size.y),
|
||||||
|
};
|
||||||
|
for layer in self.layers.iter_mut() {
|
||||||
|
layer.size = layer.view.get_min_size(req);
|
||||||
|
layer.view.layout(layer.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +72,8 @@ impl View for StackView {
|
|||||||
// The min size is the max of all children's
|
// The min size is the max of all children's
|
||||||
let mut s = Vec2::new(1,1);
|
let mut s = Vec2::new(1,1);
|
||||||
|
|
||||||
for view in self.layers.iter() {
|
for layer in self.layers.iter() {
|
||||||
let vs = view.get_min_size(size);
|
let vs = layer.view.get_min_size(size);
|
||||||
s.x = max(s.x, vs.x);
|
s.x = max(s.x, vs.x);
|
||||||
s.y = max(s.y, vs.y);
|
s.y = max(s.y, vs.y);
|
||||||
}
|
}
|
||||||
|
@ -83,12 +83,15 @@ impl <'a> Iterator for LinesIterator<'a> {
|
|||||||
Some(&self.line[start..])
|
Some(&self.line[start..])
|
||||||
} else {
|
} else {
|
||||||
let start = self.start;
|
let start = self.start;
|
||||||
let end = match self.line[start..start+self.width].rfind(" ") {
|
let (end,skip_space) = match self.line[start..start+self.width].rfind(" ") {
|
||||||
// Hard break
|
// Hard break
|
||||||
None => start + self.width,
|
None => (start + self.width, false),
|
||||||
Some(i) => start+i,
|
Some(i) => (start+i, true),
|
||||||
};
|
};
|
||||||
self.start = end;
|
self.start = end;
|
||||||
|
if skip_space {
|
||||||
|
self.start += 1;
|
||||||
|
}
|
||||||
Some(&self.line[start..end])
|
Some(&self.line[start..end])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +118,14 @@ impl View for TextView {
|
|||||||
let w = self.get_num_cols(h as usize) as u32;
|
let w = self.get_num_cols(h as usize) as u32;
|
||||||
Vec2::new(w, h)
|
Vec2::new(w, h)
|
||||||
},
|
},
|
||||||
(DimensionRequest::AtMost(_),DimensionRequest::AtMost(_)) => unreachable!(),
|
(DimensionRequest::AtMost(w),_) => {
|
||||||
|
if w >= self.content.len() as u32 {
|
||||||
|
Vec2::new(self.content.len() as u32, 1)
|
||||||
|
} else {
|
||||||
|
let h = self.get_num_lines(w as usize) as u32;
|
||||||
|
Vec2::new(w, h)
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
src/vec2.rs
24
src/vec2.rs
@ -1,6 +1,6 @@
|
|||||||
//! 2D points.
|
//! 2D points.
|
||||||
|
|
||||||
use std::ops::{Add, Sub};
|
use std::ops::{Add, Sub, Mul, Div};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
/// Simple 2D size, in characters.
|
/// Simple 2D size, in characters.
|
||||||
@ -74,3 +74,25 @@ impl Sub for Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Div<u32> for Vec2 {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn div(self, other: u32) -> Vec2 {
|
||||||
|
Vec2 {
|
||||||
|
x: self.x / other,
|
||||||
|
y: self.y / other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<u32> for Vec2 {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn mul(self, other: u32) -> Vec2 {
|
||||||
|
Vec2 {
|
||||||
|
x: self.x * other,
|
||||||
|
y: self.y * other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user