Add some documentation to view module

This commit is contained in:
Alexandre Bury 2016-07-13 20:52:24 -07:00
parent 03c400ad44
commit e166869c51
4 changed files with 36 additions and 94 deletions

View File

@ -82,7 +82,7 @@ impl Vec2 {
/// Returns a new `Vec2` with the axis `o` set to `value`. /// Returns a new `Vec2` with the axis `o` set to `value`.
pub fn with(&self, o: Orientation, value: usize) -> Self { pub fn with(&self, o: Orientation, value: usize) -> Self {
let mut other = self.clone(); let mut other = *self;
*o.get_ref(&mut other) = value; *o.get_ref(&mut other) = value;
other other
} }

View File

@ -68,6 +68,6 @@ impl<T: View> ViewWrapper for BoxView<T> {
Vec2::new(self.size.x.unwrap_or(child_size.x), Vec2::new(self.size.x.unwrap_or(child_size.x),
self.size.y.unwrap_or(child_size.y)) self.size.y.unwrap_or(child_size.y))
}.or_min(req) }
} }
} }

View File

@ -103,56 +103,6 @@ impl LinearLayout {
} }
} }
/// Returns the index of the maximum element.
/// WTF isn't it part of standard library??
fn find_max(list: &[usize]) -> usize {
let mut max_value = 0;
let mut max = 0;
for (i, &x) in list.iter().enumerate() {
if x > max_value {
max_value = x;
max = i;
}
}
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> {
// It first give a base value to everyone, which is their truncated share.
// Then, it gives the rest to the most deserving.
if weights.is_empty() {
return Vec::new();
}
let sum_weight = weights.iter().fold(0, |a, b| a + b);
if sum_weight == 0 {
return (0..weights.len()).map(|_| 0).collect();
}
let mut base = Vec::with_capacity(weights.len());
let mut rest = Vec::with_capacity(weights.len());
let mut extra = total;
for weight in &weights {
let b = total * weight / sum_weight;
extra -= b;
base.push(b);
rest.push(total * weight - b * sum_weight);
}
// TODO: better to sort (base,rest) as one array and pick the extra first.
for _ in 0..extra {
let i = find_max(&rest);
rest[i] = 0;
base[i] += 1;
}
base
}
impl View for LinearLayout { impl View for LinearLayout {
fn draw(&mut self, printer: &Printer) { fn draw(&mut self, printer: &Printer) {
// Use pre-computed sizes // Use pre-computed sizes
@ -184,50 +134,8 @@ impl View for LinearLayout {
} }
for child in &mut self.children { for child in &mut self.children {
// println_stderr!("Child size: {:?}", child.size);
child.view.layout(child.size); child.view.layout(child.size);
} }
/*
// Need to compute things again...
self.get_min_size(size);
let min_sizes: Vec<Vec2> = self.children
.iter_mut()
.map(|child| Vec2::min(size, child.view.get_min_size(size)))
.collect();
let min_size = self.orientation.stack(min_sizes.iter());
// Emulate 'non-strict inequality' on integers
// (default comparison on Vec2 is strict,
// and (0,1).cmp((1,1)) is undefined)
if !(min_size < size + (1, 1)) {
// Error! Not enough space! Emergency procedures!
return;
}
// Now share this extra space among everyone
let extras = {
let extra = size - min_size;
let space = self.orientation.get(&extra);
share(space,
self.children.iter().map(|child| child.weight).collect())
};
for (child, (child_size, extra)) in self.children
.iter_mut()
.zip(min_sizes.iter().zip(extras.iter())) {
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);
child.size = child_size;
child.view.layout(child_size);
}
*/
} }
fn get_min_size(&mut self, req: Vec2) -> Vec2 { fn get_min_size(&mut self, req: Vec2) -> Vec2 {

View File

@ -1,4 +1,38 @@
//! Defines various views to use when creating the layout. //! Defines various views to use when creating the layout.
//!
//! Views are the main building blocks of your UI.
//!
//! A view can delegate part or all of its responsabilities to child views,
//! forming a view tree. The root of this tree is a `StackView` handled
//! directly by the `Cursive` element.
//!
//! # Layout
//!
//! The layout phase is when the size and location of each view is computed.
//!
//! Each view is given an area of the screen by the `View::layout()` method.
//! With this, the view is free to plan its content, including calling
//! `View::layout()` on its own children.
//!
//! In order to determine how much space should be given each child, parents
//! can use `View::get_min_size()` on them.
//!
//!
//! ### Contracts
//!
//! When building new Views, you should respect these contracts:
//!
//! * By default, `View::layout()` should be called before any call to
//! `View::draw()` with the same available size. The only exceptions is
//! when both following conditions are met:
//! * The available size has not changed since the last call to `View::layout()`
//! * `View::needs_relayout()` returns `false`
//!
//! In this case, it is safe to omit the call to `View::layout()`.
//!
//! * The value returned by `get_min_size` should be an actually viable size,
//! no matter what the request is. This means calling `View::layout()` with
//! a size returned by `get_min_size` is **never** an error.
#[macro_use] #[macro_use]
mod view_wrapper; mod view_wrapper;