diff --git a/Cargo.toml b/Cargo.toml index 35e5a12..02859b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,3 +52,7 @@ path = "examples/select.rs" [[example]] name = "theme" path = "examples/theme.rs" + +[[example]] +name = "linear" +path = "examples/linear.rs" diff --git a/examples/linear.rs b/examples/linear.rs new file mode 100644 index 0000000..f115b61 --- /dev/null +++ b/examples/linear.rs @@ -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(); +} diff --git a/src/lib.rs b/src/lib.rs index f53abda..001a7ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ pub mod printer; pub mod vec; pub mod theme; pub mod align; +pub mod orientation; mod div; mod utf8; diff --git a/src/orientation.rs b/src/orientation.rs new file mode 100644 index 0000000..86cc6c6 --- /dev/null +++ b/src/orientation.rs @@ -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>(&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)), + } + } +} diff --git a/src/vec.rs b/src/vec.rs index eec50ce..ebe28d6 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -4,7 +4,7 @@ use std::ops::{Add, Sub, Mul, Div}; use std::cmp::{min,max,Ordering}; /// Simple 2D size, in characters. -#[derive(Clone,Copy,PartialEq)] +#[derive(Clone,Copy,PartialEq,Debug)] pub struct Vec2 { /// X coordinate (column), from left to right. pub x: usize, diff --git a/src/view/box_view.rs b/src/view/box_view.rs index f300138..6235459 100644 --- a/src/view/box_view.rs +++ b/src/view/box_view.rs @@ -1,5 +1,5 @@ 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. pub struct BoxView { @@ -29,7 +29,15 @@ impl ViewWrapper for BoxView { wrap_impl!(&self.view); - fn wrap_get_min_size(&self, _: SizeRequest) -> Vec2 { - self.size + fn wrap_get_min_size(&self, mut req: SizeRequest) -> Vec2 { + 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 } } diff --git a/src/view/linear_layout.rs b/src/view/linear_layout.rs index c069154..6763f76 100644 --- a/src/view/linear_layout.rs +++ b/src/view/linear_layout.rs @@ -1,6 +1,7 @@ use view::{View,SizeRequest,DimensionRequest}; use vec::Vec2; use printer::Printer; +use orientation::Orientation; struct Child { view: Box, @@ -13,40 +14,6 @@ pub struct LinearLayout { 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>(&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 { pub fn new(orientation: Orientation) -> Self { @@ -126,6 +93,7 @@ impl View for LinearLayout { // Use pre-computed sizes let mut offset = Vec2::zero(); for child in self.children.iter_mut() { + println!("Drawing at {:?} for {:?}", offset, child.size); child.view.draw(&printer.sub_printer(offset, child.size, true)); *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) { + println!("LAYOUT!!"); // Compute the very minimal required size let req = SizeRequest{ w: DimensionRequest::AtMost(size.x), @@ -145,6 +114,7 @@ impl View for LinearLayout { // (default comparison on Vec2 is strict) if !(min_size < size+(1,1)) { // Error! Not enough space! Emergency procedures! + println!("Min: {:?}, size: {:?}", min_size, size); return } @@ -156,7 +126,10 @@ impl View for LinearLayout { 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())) { + println!("Child size: {:?}", child_size); let mut child_size = *child_size; *self.orientation.get_ref(&mut child_size) += *extra; *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 { // First, make a naive scenario: everything will work fine. let sizes: Vec = self.children.iter().map(|view| view.view.get_min_size(req)).collect(); + println!("Views size: {:?}", sizes); self.orientation.stack(sizes.iter())