Add needs_relayout method to View trait.

Purely optimization-focused trait (it is safe to ignore it entirely).
Allows view groups to take shortcuts if they know their children didn't
change since last time.
This commit is contained in:
Alexandre Bury 2016-07-10 17:41:49 -07:00
parent 3640a10a2b
commit 99bf28dfd6
5 changed files with 51 additions and 2 deletions

View File

@ -20,6 +20,8 @@
//! siv.run(); //! siv.run();
//! } //! }
//! ``` //! ```
// #![deny(missing_docs)]
extern crate ncurses; extern crate ncurses;
extern crate toml; extern crate toml;
extern crate unicode_segmentation; extern crate unicode_segmentation;

View File

@ -9,6 +9,8 @@ pub struct LinearLayout {
children: Vec<Child>, children: Vec<Child>,
orientation: Orientation, orientation: Orientation,
focus: usize, focus: usize,
last_size: Option<Vec2>,
} }
struct Child { struct Child {
@ -24,6 +26,7 @@ impl LinearLayout {
children: Vec::new(), children: Vec::new(),
orientation: orientation, orientation: orientation,
focus: 0, focus: 0,
last_size: None,
} }
} }
@ -43,6 +46,7 @@ impl LinearLayout {
size: Vec2::zero(), size: Vec2::zero(),
weight: 0, weight: 0,
}); });
self.last_size = None;
self self
} }
@ -122,6 +126,20 @@ impl View for LinearLayout {
} }
} }
fn needs_relayout(&self) -> bool {
if self.last_size == None {
return true;
}
for child in &self.children {
if child.view.needs_relayout() {
return true;
}
}
false
}
fn layout(&mut self, size: Vec2) { fn layout(&mut self, size: Vec2) {
// Compute the very minimal required size // Compute the very minimal required size
// Look how mean we are: we offer the whole size to every child. // Look how mean we are: we offer the whole size to every child.

View File

@ -69,14 +69,31 @@ pub trait View {
Vec2::new(1, 1) Vec2::new(1, 1)
} }
/// Called once the size for this view has been decided, so it can /// Returns `true` if the view content changed since last layout phase.
/// propagate the information to its children. ///
/// This is mostly an optimisation for views where the layout phase is
/// expensive.
///
/// * Views can ignore it and always return true (default implementation).
/// They will always be assumed to have changed.
/// * View Groups can ignore it and always re-layout their children.
/// * If they call `get_min_size` or `layout` with stable parameters,
/// the children may cache the result themselves and speed up the
/// process anyway.
fn needs_relayout(&self) -> bool {
true
}
/// Called once the size for this view has been decided,
///
/// View groups should propagate the information to their children.
fn layout(&mut self, Vec2) {} fn layout(&mut self, Vec2) {}
/// Draws the view with the given printer (includes bounds) and focus. /// Draws the view with the given printer (includes bounds) and focus.
fn draw(&mut self, printer: &Printer); fn draw(&mut self, printer: &Printer);
/// Finds the view pointed to by the given path. /// Finds the view pointed to by the given path.
///
/// Returns None if the path doesn't lead to a view. /// Returns None if the path doesn't lead to a view.
fn find(&mut self, &Selector) -> Option<&mut Any> { fn find(&mut self, &Selector) -> Option<&mut Any> {
None None

View File

@ -230,6 +230,10 @@ impl View for TextView {
EventResult::Consumed(None) EventResult::Consumed(None)
} }
fn needs_relayout(&self) -> bool {
self.last_size == None
}
fn get_min_size(&mut self, size: Vec2) -> Vec2 { fn get_min_size(&mut self, size: Vec2) -> Vec2 {
// If we have no directive, ask for a single big line. // If we have no directive, ask for a single big line.
// TODO: what if the text has newlines?? // TODO: what if the text has newlines??

View File

@ -43,6 +43,10 @@ pub trait ViewWrapper {
fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> { fn wrap_find(&mut self, selector: &Selector) -> Option<&mut Any> {
self.get_view_mut().find(selector) self.get_view_mut().find(selector)
} }
fn wrap_needs_relayout(&self) -> bool {
self.get_view().needs_relayout()
}
} }
impl<T: ViewWrapper> View for T { impl<T: ViewWrapper> View for T {
@ -69,6 +73,10 @@ impl<T: ViewWrapper> View for T {
fn find(&mut self, selector: &Selector) -> Option<&mut Any> { fn find(&mut self, selector: &Selector) -> Option<&mut Any> {
self.wrap_find(selector) self.wrap_find(selector)
} }
fn needs_relayout(&self) -> bool {
self.wrap_needs_relayout()
}
} }
/// Convenient macro to implement to two methods required for the ViewWrapper trait. /// Convenient macro to implement to two methods required for the ViewWrapper trait.