Update documentation

This commit is contained in:
Alexandre Bury 2015-06-08 15:38:10 -07:00
parent daaff26e1c
commit df11b4f1f0
5 changed files with 48 additions and 18 deletions

View File

@ -3,20 +3,20 @@ extern crate cursive;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::{Dialog,TextView,LinearLayout,BoxView}; use cursive::view::{Dialog,TextView,LinearLayout,BoxView};
use cursive::align::HAlign; use cursive::align::HAlign;
use cursive::orientation::Orientation;
fn main() { fn main() {
let mut siv = Cursive::new(); let mut siv = Cursive::new();
// Some longish content // Some description text
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."; 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"); // We'll create a dialog with a TextView serving as a title
siv.add_layer( siv.add_layer(
Dialog::new( Dialog::new(
LinearLayout::new(Orientation::Vertical) LinearLayout::vertical()
.child(TextView::new("Title").h_align(HAlign::Center)) .child(TextView::new("Title").h_align(HAlign::Center))
// Box the textview, so it doesn't get too wide.
// A 0 height value means it will be unconstrained.
.child(BoxView::new((30,0), TextView::new(text)))) .child(BoxView::new((30,0), TextView::new(text))))
.button("Quit", |s| s.quit()) .button("Quit", |s| s.quit())
.h_align(HAlign::Center)); .h_align(HAlign::Center));

View File

@ -20,6 +20,7 @@ pub enum EventResult {
Consumed(Option<Rc<Callback>>), Consumed(Option<Rc<Callback>>),
} }
/// Represents a key, or a combination of keys.
#[derive(PartialEq,Eq,Clone,Copy,Hash)] #[derive(PartialEq,Eq,Clone,Copy,Hash)]
pub enum Key { pub enum Key {
/// Both Enter and numpad Enter /// Both Enter and numpad Enter
@ -200,9 +201,13 @@ impl fmt::Display for Key {
} }
} }
/// Represents an event as seen by the application.
///
#[derive(PartialEq,Eq,Clone,Copy,Hash)] #[derive(PartialEq,Eq,Clone,Copy,Hash)]
pub enum Event { pub enum Event {
/// A text character was entered.
CharEvent(char), CharEvent(char),
/// A key was pressed.
KeyEvent(Key), KeyEvent(Key),
} }

View File

@ -1,12 +1,18 @@
//! Define an Orientation and associated methods.
use vec::Vec2; use vec::Vec2;
/// Describes a vertical or horizontal orientation for a view.
#[derive(Clone,Copy,PartialEq)] #[derive(Clone,Copy,PartialEq)]
pub enum Orientation { pub enum Orientation {
/// Horizontal orientation
Horizontal, Horizontal,
/// Vertical orientation
Vertical, Vertical,
} }
impl Orientation { impl Orientation {
/// Returns the component of the given vector corresponding to this orientation.
/// (Horizontal will return the x value, and Vertical will return the y value.)
pub fn get(&self, v: &Vec2) -> usize { pub fn get(&self, v: &Vec2) -> usize {
match *self { match *self {
Orientation::Horizontal => v.x, Orientation::Horizontal => v.x,
@ -14,6 +20,7 @@ impl Orientation {
} }
} }
/// Returns the other orientation.
pub fn swap(&self) -> Self { pub fn swap(&self) -> Self {
match *self { match *self {
Orientation::Horizontal => Orientation::Vertical, Orientation::Horizontal => Orientation::Vertical,
@ -21,6 +28,8 @@ impl Orientation {
} }
} }
/// Returns a mutable reference to the component of the given vector
/// corresponding to this orientation.
pub fn get_ref<'a,'b>(&'a self, v: &'b mut Vec2) -> &'b mut usize { pub fn get_ref<'a,'b>(&'a self, v: &'b mut Vec2) -> &'b mut usize {
match *self { match *self {
Orientation::Horizontal => &mut v.x, Orientation::Horizontal => &mut v.x,
@ -28,6 +37,11 @@ impl Orientation {
} }
} }
/// Takes an iterator on sizes, and stack them in the current orientation,
/// returning the size of the required bounding box.
///
/// For an horizontal view, returns (Sum(x), Max(y)).
/// For a vertical view, returns (Max(x),Sum(y)).
pub fn stack<'a,T: Iterator<Item=&'a Vec2>>(&self, iter: T) -> Vec2 { pub fn stack<'a,T: Iterator<Item=&'a Vec2>>(&self, iter: T) -> Vec2 {
match *self { match *self {
Orientation::Horizontal => iter.fold(Vec2::zero(), |a,b| a.stack_horizontal(&b)), Orientation::Horizontal => iter.fold(Vec2::zero(), |a,b| a.stack_horizontal(&b)),

View File

@ -4,20 +4,21 @@ use printer::Printer;
use orientation::Orientation; use orientation::Orientation;
use event::{Event,EventResult,Key}; use event::{Event,EventResult,Key};
/// Arranges its children linearly according to its orientation.
pub struct LinearLayout {
children: Vec<Child>,
orientation: Orientation,
focus: usize,
}
struct Child { struct Child {
view: Box<View>, view: Box<View>,
size: Vec2, size: Vec2,
weight: usize, weight: usize,
} }
pub struct LinearLayout {
children: Vec<Child>,
orientation: Orientation,
focus: usize,
}
impl LinearLayout { impl LinearLayout {
/// Creates a new layout with the given orientation.
pub fn new(orientation: Orientation) -> Self { pub fn new(orientation: Orientation) -> Self {
LinearLayout { LinearLayout {
children: Vec::new(), children: Vec::new(),
@ -26,12 +27,16 @@ impl LinearLayout {
} }
} }
/// Modifies the weight of the last child added.
///
/// It is an error to call this before adding a child (and it will panic).
pub fn weight(mut self, weight: usize) -> Self { pub fn weight(mut self, weight: usize) -> Self {
self.children.last_mut().unwrap().weight = weight; self.children.last_mut().unwrap().weight = weight;
self self
} }
/// Adds a child to the layout.
pub fn child<V: View + 'static>(mut self, view: V) -> Self { pub fn child<V: View + 'static>(mut self, view: V) -> Self {
self.children.push(Child { self.children.push(Child {
view: Box::new(view), view: Box::new(view),
@ -42,14 +47,19 @@ impl LinearLayout {
self self
} }
/// Creates a new vertical layout.
pub fn vertical() -> Self { pub fn vertical() -> Self {
LinearLayout::new(Orientation::Vertical) LinearLayout::new(Orientation::Vertical)
} }
/// Creates a new horizontal layout.
pub fn horizontal() -> Self { pub fn horizontal() -> Self {
LinearLayout::new(Orientation::Horizontal) LinearLayout::new(Orientation::Horizontal)
} }
} }
/// Returns the index of the maximum element.
/// WTF isn't it part of standard library??
fn find_max(list: &Vec<usize>) -> usize { fn find_max(list: &Vec<usize>) -> usize {
let mut max_value = 0; let mut max_value = 0;
let mut max = 0; let mut max = 0;
@ -62,7 +72,12 @@ fn find_max(list: &Vec<usize>) -> usize {
max max
} }
/// Given a total number of points and a list of weights,
/// try to share the points according to the weight,
/// rounding properly and conserving the sum of points.
fn share(total: usize, weights: Vec<usize>) -> Vec<usize> { fn share(total: usize, weights: Vec<usize>) -> Vec<usize> {
// It first give a base value to everyone, which is their truncated share.
// Then, it gives the rest to the most deserving.
if weights.len() == 0 { return Vec::new(); } if weights.len() == 0 { return Vec::new(); }
let sum_weight = weights.iter().fold(0,|a,b| a+b); let sum_weight = weights.iter().fold(0,|a,b| a+b);
@ -96,7 +111,6 @@ 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);
@ -104,7 +118,6 @@ 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),
@ -117,7 +130,6 @@ 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
} }
@ -129,10 +141,8 @@ 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);
@ -144,7 +154,6 @@ 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())

View File

@ -71,7 +71,9 @@ pub trait View {
/// Selects a single view (if any) in the tree. /// Selects a single view (if any) in the tree.
pub enum Selector<'a> { pub enum Selector<'a> {
/// Selects a view from its ID
Id(&'a str), Id(&'a str),
/// Selects a view from its path
Path(&'a ViewPath), Path(&'a ViewPath),
} }