Add scrollable flag to TextViews

This commit is contained in:
Alexandre Bury 2016-07-16 17:08:17 -07:00
parent 89468d1786
commit 5ee8706582
3 changed files with 46 additions and 7 deletions

View File

@ -17,7 +17,7 @@ fn main() {
.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. // Box the textview, so it doesn't get too wide.
// A 0 height value means it will be unconstrained. // A 0 height value means it will be unconstrained.
.child(BoxView::fixed_width(30, TextView::new(text))) .child(BoxView::fixed_width(30, TextView::new(text).scrollable(false)))
.child(BoxView::fixed_width(30, TextView::new(text))) .child(BoxView::fixed_width(30, TextView::new(text)))
.child(BoxView::fixed_width(30, TextView::new(text))) .child(BoxView::fixed_width(30, TextView::new(text)))
.child(BoxView::fixed_width(30, TextView::new(text)))) .child(BoxView::fixed_width(30, TextView::new(text))))

View File

@ -185,8 +185,8 @@ impl SizeCache {
/// * `size` must fit inside `req`. /// * `size` must fit inside `req`.
/// * for each dimension, `constrained = (size == req)` /// * for each dimension, `constrained = (size == req)`
fn build(size: Vec2, req: Vec2) -> XY<Self> { fn build(size: Vec2, req: Vec2) -> XY<Self> {
XY::new(SizeCache::new(size.x, size.x == req.x), XY::new(SizeCache::new(size.x, size.x >= req.x),
SizeCache::new(size.y, size.y == req.y)) SizeCache::new(size.y, size.y >= req.y))
} }
} }

View File

@ -1,4 +1,5 @@
use XY; use XY;
use With;
use direction::Direction; use direction::Direction;
use vec::Vec2; use vec::Vec2;
use view::View; use view::View;
@ -19,6 +20,9 @@ pub struct TextView {
align: Align, align: Align,
// If `false`, disable scrolling.
scrollable: bool,
// ScrollBase make many scrolling-related things easier // ScrollBase make many scrolling-related things easier
scrollbase: ScrollBase, scrollbase: ScrollBase,
last_size: Option<XY<SizeCache>>, last_size: Option<XY<SizeCache>>,
@ -48,6 +52,7 @@ impl TextView {
TextView { TextView {
content: content.to_string(), content: content.to_string(),
rows: Vec::new(), rows: Vec::new(),
scrollable: true,
scrollbase: ScrollBase::new(), scrollbase: ScrollBase::new(),
align: Align::top_left(), align: Align::top_left(),
last_size: None, last_size: None,
@ -55,6 +60,24 @@ impl TextView {
} }
} }
/// Enable or disable the view's scrolling capabilities.
///
/// When disabled, the view will never attempt to scroll
/// (and will always ask for the full height).
pub fn set_scrollable(&mut self, scrollable: bool) {
self.scrollable = scrollable;
}
/// Enable or disable the view's scrolling capabilities.
///
/// When disabled, the view will never attempt to scroll
/// (and will always ask for the full height).
///
/// Chainable variant.
pub fn scrollable(self, scrollable: bool) -> Self {
self.with(|s| s.set_scrollable(scrollable))
}
/// Sets the horizontal alignment for this view. /// Sets the horizontal alignment for this view.
pub fn h_align(mut self, h: HAlign) -> Self { pub fn h_align(mut self, h: HAlign) -> Self {
self.align.h = h; self.align.h = h;
@ -100,7 +123,7 @@ impl TextView {
// Recompute // Recompute
self.rows = LinesIterator::new(&self.content, size.x).collect(); self.rows = LinesIterator::new(&self.content, size.x).collect();
let mut scrollbar = 0; let mut scrollbar = 0;
if self.rows.len() > size.y { if self.scrollable && self.rows.len() > size.y {
scrollbar = 2; scrollbar = 2;
// If we're too high, include a scrollbar // If we're too high, include a scrollbar
self.rows = LinesIterator::new(&self.content, self.rows = LinesIterator::new(&self.content,
@ -108,6 +131,7 @@ impl TextView {
.collect(); .collect();
} }
// Desired width, including the scrollbar.
self.width = self.rows self.width = self.rows
.iter() .iter()
.map(|row| row.width) .map(|row| row.width)
@ -115,8 +139,15 @@ impl TextView {
.map(|w| w + scrollbar); .map(|w| w + scrollbar);
// Our resulting size. // Our resulting size.
let my_size = // We can't go lower, width-wise.
size.or_min((self.width.unwrap_or(0), self.rows.len()));
let mut my_size = Vec2::new(self.width.unwrap_or(0),
self.rows.len());
if self.scrollable && my_size.y > size.y {
my_size.y = size.y;
}
self.last_size = Some(SizeCache::build(my_size, size)); self.last_size = Some(SizeCache::build(my_size, size));
} }
} }
@ -237,7 +268,15 @@ impl View for TextView {
fn get_min_size(&mut self, size: Vec2) -> Vec2 { fn get_min_size(&mut self, size: Vec2) -> Vec2 {
self.compute_rows(size); self.compute_rows(size);
size.or_min((self.width.unwrap_or(0), self.rows.len()))
// This is what we'd like
let mut ideal = Vec2::new(self.width.unwrap_or(0), self.rows.len());
if self.scrollable && ideal.y > size.y {
ideal.y = size.y;
}
ideal
} }
fn take_focus(&mut self, _: Direction) -> bool { fn take_focus(&mut self, _: Direction) -> bool {