diff --git a/src/view/dialog.rs b/src/view/dialog.rs index c27bb1f..3bb0bfc 100644 --- a/src/view/dialog.rs +++ b/src/view/dialog.rs @@ -24,7 +24,8 @@ enum Focus { /// /// ``` /// # use cursive::view::{Dialog,TextView}; -/// let dialog = Dialog::new(TextView::new("Hello!")).button("Ok", |s| s.quit()); +/// let dialog = Dialog::new(TextView::new("Hello!")) +/// .button("Ok", |s| s.quit()); /// ``` pub struct Dialog { title: String, @@ -108,8 +109,8 @@ impl Dialog { impl View for Dialog { fn draw(&mut self, printer: &Printer) { - // This will be the height used by the buttons. - let mut height = 0; + // This will be the buttons_height used by the buttons. + let mut buttons_height = 0; // Current horizontal position of the next button we'll draw. // Sum of the sizes + len-1 for margins @@ -123,7 +124,9 @@ impl View for Dialog { }; let overhead = self.padding + self.borders; let mut offset = overhead.left + - self.align.h.get_offset(width, printer.size.x - overhead.horizontal()); + self.align + .h + .get_offset(width, printer.size.x - overhead.horizontal()); let y = printer.size.y - self.padding.bottom - self.borders.bottom - 1; for (i, button) in self.buttons.iter_mut().enumerate() { @@ -135,16 +138,19 @@ impl View for Dialog { // Keep 1 blank between two buttons offset += size.x + 1; // Also keep 1 blank above the buttons - height = max(height, size.y + 1); + buttons_height = max(buttons_height, size.y + 1); } // What do we have left? - let inner_size = printer.size - Vec2::new(0, height) - self.borders.combined() - + let inner_size = printer.size - Vec2::new(0, buttons_height) - + self.borders.combined() - self.padding.combined(); - self.content.draw(&printer.sub_printer(self.borders.top_left() + self.padding.top_left(), - inner_size, - self.focus == Focus::Content)); + self.content + .draw(&printer.sub_printer(self.borders.top_left() + + self.padding.top_left(), + inner_size, + self.focus == Focus::Content)); printer.print_box(Vec2::new(0, 0), printer.size); @@ -154,16 +160,17 @@ impl View for Dialog { printer.print((x - 2, 0), "┤ "); printer.print((x + len, 0), " ├"); - printer.with_color(ColorStyle::TitlePrimary, |p| p.print((x, 0), &self.title)); + printer.with_color(ColorStyle::TitlePrimary, + |p| p.print((x, 0), &self.title)); } } fn get_min_size(&mut self, req: Vec2) -> Vec2 { // Padding and borders are not available for kids. - let content_req = req - (self.padding.combined() + self.borders.combined()); - let content_size = self.content.get_min_size(content_req); + let nomans_land = self.padding.combined() + self.borders.combined(); + // Buttons are not flexible, so their size doesn't depend on ours. let mut buttons_size = Vec2::new(0, 0); if !self.buttons.is_empty() { buttons_size.x += self.buttons.len() - 1; @@ -174,6 +181,10 @@ impl View for Dialog { buttons_size.y = max(buttons_size.y, s.y + 1); } + // We also remove one row for the buttons. + let content_req = req - (nomans_land + Vec2::new(0, buttons_size.y)); + let content_size = self.content.get_min_size(content_req); + // On the Y axis, we add buttons and content. // On the X axis, we take the max. let mut inner_size = Vec2::new(max(content_size.x, buttons_size.x), @@ -245,7 +256,7 @@ impl View for Dialog { // Left and Right move to other buttons Event::Key(Key::Right) if i + 1 < self.buttons - .len() => { + .len() => { self.focus = Focus::Button(i + 1); EventResult::Consumed(None) } diff --git a/src/view/text_view.rs b/src/view/text_view.rs index 033469a..8682318 100644 --- a/src/view/text_view.rs +++ b/src/view/text_view.rs @@ -1,5 +1,3 @@ -use std::cmp::max; - use vec::Vec2; use view::View; use printer::Printer; @@ -39,24 +37,6 @@ fn strip_last_newline(content: &str) -> &str { } } -/// Returns the number of lines required to display the given text with the -/// specified maximum line width. -fn get_line_span(line: &str, max_width: usize) -> usize { - // TODO: this method is stupid. Look at LinesIterator and do the same - // (Or use a common function? Better!) - let mut lines = 1; - let mut length = 0; - for l in line.split(' ').map(|word| word.width()) { - length += l; - if length > max_width { - length = l; - lines += 1; - } - length += 1; - } - lines -} - impl TextView { /// Creates a new TextView with the given content. pub fn new(content: &str) -> Self { @@ -104,36 +84,16 @@ impl TextView { &self.content } - /// Returns the number of lines required to display the content - /// with the given width. - fn get_num_lines(&self, max_width: usize) -> usize { - self.content - .split('\n') - .map(|line| get_line_span(line, max_width)) - .fold(0, |sum, x| sum + x) - } - - // In the absence of any constraint, what size would we like? - fn get_ideal_size(&self) -> Vec2 { - let mut max_width = 0; - let mut height = 0; - - for line in self.content.split('\n') { - height += 1; - max_width = max(max_width, line.width()); - } - - Vec2::new(max_width, height) - } - fn is_cache_valid(&self, size: Vec2) -> bool { match self.last_size { None => false, - Some(last) => if last.x != size.x { - false - } else { - (last.y < self.rows.len()) == (size.y < self.rows.len()) - }, + Some(last) => { + if last.x != size.x { + false + } else { + (last.y < self.rows.len()) == (size.y < self.rows.len()) + } + } } } @@ -145,11 +105,16 @@ impl TextView { if self.rows.len() > size.y { scrollbar = 2; // If we're too high, include a scrollbar - self.rows = LinesIterator::new(&self.content, size.x - scrollbar) + self.rows = LinesIterator::new(&self.content, + size.x - scrollbar) .collect(); } - self.width = self.rows.iter().map(|row| row.width).max().map(|w| w + scrollbar); + self.width = self.rows + .iter() + .map(|row| row.width) + .max() + .map(|w| w + scrollbar); self.last_size = Some(size); } @@ -208,10 +173,14 @@ impl<'a> Iterator for LinesIterator<'a> { } // Keep adding indivisible tokens - let head_bytes = match head_bytes(content.split(' '), self.width, " ") { - 0 => head_bytes(content.graphemes(true), self.width, ""), - other => { self.start += 1; other }, - }; + let head_bytes = + match head_bytes(content.split(' '), self.width, " ") { + 0 => head_bytes(content.graphemes(true), self.width, ""), + other => { + self.start += 1; + other + } + }; self.start += head_bytes; @@ -228,9 +197,8 @@ impl View for TextView { let h = self.rows.len(); let offset = self.align.v.get_offset(h, printer.size.y); - let printer = &printer.sub_printer(Vec2::new(0, offset), - printer.size, - true); + let printer = + &printer.sub_printer(Vec2::new(0, offset), printer.size, true); self.scrollbase.draw(printer, |printer, i| { let row = &self.rows[i]; @@ -253,9 +221,7 @@ impl View for TextView { self.scrollbase.scroll_up(1) } Event::Key(Key::Down) if self.scrollbase - .can_scroll_down() => { - self.scrollbase.scroll_down(1) - } + .can_scroll_down() => self.scrollbase.scroll_down(1), Event::Key(Key::PageDown) => self.scrollbase.scroll_down(10), Event::Key(Key::PageUp) => self.scrollbase.scroll_up(10), _ => return EventResult::Ignored, @@ -284,23 +250,24 @@ impl View for TextView { } } -fn head_bytes<'a, I: Iterator>(iter: I, width: usize, overhead: &str) - -> usize { +fn head_bytes<'a, I: Iterator>(iter: I, width: usize, + overhead: &str) + -> usize { let overhead_width = overhead.width(); let overhead_len = overhead.len(); let sum = iter.scan(0, |w, token| { - *w += token.width(); - if *w > width { - None - } else { - // Add a space - *w += overhead_width; - Some(token) - } - }) - .map(|token| token.len() + overhead_len) - .fold(0, |a, b| a + b); + *w += token.width(); + if *w > width { + None + } else { + // Add a space + *w += overhead_width; + Some(token) + } + }) + .map(|token| token.len() + overhead_len) + .fold(0, |a, b| a + b); // We counted overhead_len once too many times, // but only if the iterator was non empty.