BugFix in LinearLayout

And add a simple linear example.
This commit is contained in:
Alexandre Bury 2015-06-08 12:23:36 -07:00
parent df5ff808e3
commit 40af72a567
7 changed files with 86 additions and 38 deletions

View File

@ -52,3 +52,7 @@ path = "examples/select.rs"
[[example]] [[example]]
name = "theme" name = "theme"
path = "examples/theme.rs" path = "examples/theme.rs"
[[example]]
name = "linear"
path = "examples/linear.rs"

25
examples/linear.rs Normal file
View File

@ -0,0 +1,25 @@
extern crate cursive;
use cursive::Cursive;
use cursive::view::{Dialog,TextView,LinearLayout,BoxView};
use cursive::align::HAlign;
use cursive::orientation::Orientation;
fn main() {
let mut siv = Cursive::new();
// Some longish content
let text = "This is a very simple example of linear layout. Two views are present, a short title above, and this text. The text has a fixed width, and the title is centered horizontally.";
println!("Blaaah");
siv.add_layer(
Dialog::new(
LinearLayout::new(Orientation::Vertical)
.child(TextView::new("Title").h_align(HAlign::Center))
.child(BoxView::new((30,0), TextView::new(text))))
.button("Quit", |s| s.quit())
.h_align(HAlign::Center));
siv.run();
}

View File

@ -29,6 +29,7 @@ pub mod printer;
pub mod vec; pub mod vec;
pub mod theme; pub mod theme;
pub mod align; pub mod align;
pub mod orientation;
mod div; mod div;
mod utf8; mod utf8;

36
src/orientation.rs Normal file
View File

@ -0,0 +1,36 @@
use vec::Vec2;
pub enum Orientation {
Horizontal,
Vertical,
}
impl Orientation {
pub fn get(&self, v: &Vec2) -> usize {
match *self {
Orientation::Horizontal => v.x,
Orientation::Vertical => v.y,
}
}
pub fn swap(&self) -> Self {
match *self {
Orientation::Horizontal => Orientation::Vertical,
Orientation::Vertical => Orientation::Horizontal,
}
}
pub fn get_ref<'a,'b>(&'a self, v: &'b mut Vec2) -> &'b mut usize {
match *self {
Orientation::Horizontal => &mut v.x,
Orientation::Vertical => &mut v.y,
}
}
pub fn stack<'a,T: Iterator<Item=&'a Vec2>>(&self, iter: T) -> Vec2 {
match *self {
Orientation::Horizontal => iter.fold(Vec2::zero(), |a,b| a.stack_horizontal(&b)),
Orientation::Vertical => iter.fold(Vec2::zero(), |a,b| a.stack_vertical(&b)),
}
}
}

View File

@ -4,7 +4,7 @@ use std::ops::{Add, Sub, Mul, Div};
use std::cmp::{min,max,Ordering}; use std::cmp::{min,max,Ordering};
/// Simple 2D size, in characters. /// Simple 2D size, in characters.
#[derive(Clone,Copy,PartialEq)] #[derive(Clone,Copy,PartialEq,Debug)]
pub struct Vec2 { pub struct Vec2 {
/// X coordinate (column), from left to right. /// X coordinate (column), from left to right.
pub x: usize, pub x: usize,

View File

@ -1,5 +1,5 @@
use vec::{Vec2,ToVec2}; use vec::{Vec2,ToVec2};
use super::{View,ViewWrapper,SizeRequest}; use super::{View,ViewWrapper,SizeRequest,DimensionRequest};
/// BoxView is a wrapper around an other view, with a given minimum size. /// BoxView is a wrapper around an other view, with a given minimum size.
pub struct BoxView<T: View> { pub struct BoxView<T: View> {
@ -29,7 +29,15 @@ impl <T: View> ViewWrapper for BoxView<T> {
wrap_impl!(&self.view); wrap_impl!(&self.view);
fn wrap_get_min_size(&self, _: SizeRequest) -> Vec2 { fn wrap_get_min_size(&self, mut req: SizeRequest) -> Vec2 {
self.size if self.size.x > 0 { req.w = DimensionRequest::AtMost(self.size.x); }
if self.size.y > 0 { req.h = DimensionRequest::AtMost(self.size.y); }
let mut size = self.view.get_min_size(req);
if self.size.x > 0 { size.x = self.size.x; }
if self.size.y > 0 { size.y = self.size.y; }
size
} }
} }

View File

@ -1,6 +1,7 @@
use view::{View,SizeRequest,DimensionRequest}; use view::{View,SizeRequest,DimensionRequest};
use vec::Vec2; use vec::Vec2;
use printer::Printer; use printer::Printer;
use orientation::Orientation;
struct Child { struct Child {
view: Box<View>, view: Box<View>,
@ -13,40 +14,6 @@ pub struct LinearLayout {
orientation: Orientation, orientation: Orientation,
} }
pub enum Orientation {
Horizontal,
Vertical,
}
impl Orientation {
fn get(&self, v: &Vec2) -> usize {
match *self {
Orientation::Horizontal => v.x,
Orientation::Vertical => v.y,
}
}
fn swap(&self) -> Self {
match *self {
Orientation::Horizontal => Orientation::Vertical,
Orientation::Vertical => Orientation::Horizontal,
}
}
fn get_ref<'a,'b>(&'a self, v: &'b mut Vec2) -> &'b mut usize {
match *self {
Orientation::Horizontal => &mut v.x,
Orientation::Vertical => &mut v.y,
}
}
fn stack<'a,T: Iterator<Item=&'a Vec2>>(&self, iter: T) -> Vec2 {
match *self {
Orientation::Horizontal => iter.fold(Vec2::zero(), |a,b| a.stack_horizontal(&b)),
Orientation::Vertical => iter.fold(Vec2::zero(), |a,b| a.stack_vertical(&b)),
}
}
}
impl LinearLayout { impl LinearLayout {
pub fn new(orientation: Orientation) -> Self { pub fn new(orientation: Orientation) -> Self {
@ -126,6 +93,7 @@ impl View for LinearLayout {
// Use pre-computed sizes // Use pre-computed sizes
let mut offset = Vec2::zero(); let mut offset = Vec2::zero();
for child in self.children.iter_mut() { for child in self.children.iter_mut() {
println!("Drawing at {:?} for {:?}", offset, child.size);
child.view.draw(&printer.sub_printer(offset, child.size, true)); child.view.draw(&printer.sub_printer(offset, child.size, true));
*self.orientation.get_ref(&mut offset) += self.orientation.get(&child.size); *self.orientation.get_ref(&mut offset) += self.orientation.get(&child.size);
@ -133,6 +101,7 @@ impl View for LinearLayout {
} }
fn layout(&mut self, size: Vec2) { fn layout(&mut self, size: Vec2) {
println!("LAYOUT!!");
// Compute the very minimal required size // Compute the very minimal required size
let req = SizeRequest{ let req = SizeRequest{
w: DimensionRequest::AtMost(size.x), w: DimensionRequest::AtMost(size.x),
@ -145,6 +114,7 @@ impl View for LinearLayout {
// (default comparison on Vec2 is strict) // (default comparison on Vec2 is strict)
if !(min_size < size+(1,1)) { if !(min_size < size+(1,1)) {
// Error! Not enough space! Emergency procedures! // Error! Not enough space! Emergency procedures!
println!("Min: {:?}, size: {:?}", min_size, size);
return return
} }
@ -156,7 +126,10 @@ impl View for LinearLayout {
share(space, self.children.iter().map(|child| child.weight).collect()) share(space, self.children.iter().map(|child| child.weight).collect())
}; };
println!("Sizes: {}, {}, {}", self.children.len(), min_sizes.len(), extras.len());
for (child,(child_size,extra)) in self.children.iter_mut().zip(min_sizes.iter().zip(extras.iter())) { for (child,(child_size,extra)) in self.children.iter_mut().zip(min_sizes.iter().zip(extras.iter())) {
println!("Child size: {:?}", child_size);
let mut child_size = *child_size; let mut child_size = *child_size;
*self.orientation.get_ref(&mut child_size) += *extra; *self.orientation.get_ref(&mut child_size) += *extra;
*self.orientation.swap().get_ref(&mut child_size) = self.orientation.swap().get(&size); *self.orientation.swap().get_ref(&mut child_size) = self.orientation.swap().get(&size);
@ -168,6 +141,7 @@ impl View for LinearLayout {
fn get_min_size(&self, req: SizeRequest) -> Vec2 { fn get_min_size(&self, req: SizeRequest) -> Vec2 {
// First, make a naive scenario: everything will work fine. // First, make a naive scenario: everything will work fine.
let sizes: Vec<Vec2> = self.children.iter().map(|view| view.view.get_min_size(req)).collect(); let sizes: Vec<Vec2> = self.children.iter().map(|view| view.view.get_min_size(req)).collect();
println!("Views size: {:?}", sizes);
self.orientation.stack(sizes.iter()) self.orientation.stack(sizes.iter())