From 840fd627b78a990df639d7e3c5e6845ee16c13c7 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Tue, 24 Jul 2018 19:38:24 -0700 Subject: [PATCH] Remove internal scrolling from SelectView --- examples/select.rs | 2 +- src/views/select_view.rs | 149 +++++++++------------------------------ 2 files changed, 36 insertions(+), 115 deletions(-) diff --git a/examples/select.rs b/examples/select.rs index 961481a..0b5a48e 100644 --- a/examples/select.rs +++ b/examples/select.rs @@ -38,7 +38,7 @@ fn main() { // Let's add a BoxView to keep the list at a reasonable size // (it can scroll anyway). siv.add_layer( - Dialog::around(select.fixed_size((20, 10))) + Dialog::around(select.scrollable().fixed_size((20, 10))) .title("Where are you from?"), ); diff --git a/src/views/select_view.rs b/src/views/select_view.rs index e19816d..f48731a 100644 --- a/src/views/select_view.rs +++ b/src/views/select_view.rs @@ -10,7 +10,7 @@ use std::rc::Rc; use theme::ColorStyle; use unicode_width::UnicodeWidthStr; use vec::Vec2; -use view::{Position, ScrollBase, View}; +use view::{Position, View}; use views::MenuPopup; use Cursive; use Printer; @@ -51,7 +51,6 @@ pub struct SelectView { enabled: bool, // the focus needs to be manipulable from callbacks focus: Rc>, - scrollbase: ScrollBase, // This is a custom callback to include a &T. // It will be called whenever "Enter" is pressed. on_submit: Option>, @@ -79,7 +78,6 @@ impl SelectView { items: Vec::new(), enabled: true, focus: Rc::new(Cell::new(0)), - scrollbase: ScrollBase::new(), on_select: None, on_submit: None, align: Align::top_left(), @@ -353,7 +351,6 @@ impl SelectView { min(i, self.len() - 1) }; self.focus.set(i); - self.scrollbase.scroll_to(i); self.make_select_cb().unwrap_or_else(Callback::dummy) } @@ -386,9 +383,6 @@ impl SelectView { /// ``` pub fn select_up(&mut self, n: usize) -> Callback { self.focus_up(n); - let focus = self.focus(); - self.scrollbase.scroll_to(focus); - self.make_select_cb().unwrap_or_else(Callback::dummy) } @@ -399,19 +393,14 @@ impl SelectView { /// You should run this callback with a `&mut Cursive`. pub fn select_down(&mut self, n: usize) -> Callback { self.focus_down(n); - let focus = self.focus(); - self.scrollbase.scroll_to(focus); - self.make_select_cb().unwrap_or_else(Callback::dummy) } - // Low-level focus change. Does not fix scrollbase. fn focus_up(&mut self, n: usize) { let focus = self.focus().saturating_sub(n); self.focus.set(focus); } - // Low-level focus change. Does not fix scrollbase. fn focus_down(&mut self, n: usize) { let focus = min(self.focus() + n, self.items.len().saturating_sub(1)); self.focus.set(focus); @@ -427,7 +416,6 @@ impl SelectView { } fn on_event_regular(&mut self, event: Event) -> EventResult { - let mut fix_scroll = true; match event { Event::Key(Key::Up) if self.focus() > 0 => self.focus_up(1), Event::Key(Key::Down) if self.focus() + 1 < self.items.len() => { @@ -440,92 +428,34 @@ impl SelectView { self.focus.set(self.items.len().saturating_sub(1)) } Event::Mouse { - event: MouseEvent::WheelDown, - .. - } - if self.scrollbase.can_scroll_down() => - { - fix_scroll = false; - self.scrollbase.scroll_down(5); - } - Event::Mouse { - event: MouseEvent::WheelUp, - .. - } - if self.scrollbase.can_scroll_up() => - { - fix_scroll = false; - self.scrollbase.scroll_up(5); - } - Event::Mouse { - event: MouseEvent::Press(MouseButton::Left), + event: MouseEvent::Press(_), position, offset, } if position .checked_sub(offset) .map(|position| { - self.scrollbase.start_drag(position, self.last_size.x) + position < self.last_size && position.y < self.len() }) .unwrap_or(false) => { - fix_scroll = false; + self.focus.set(position.y - offset.y) } - Event::Mouse { - event: MouseEvent::Hold(MouseButton::Left), - position, - offset, - } => { - // If the mouse is dragged, we always consume the event. - fix_scroll = false; - let position = position.saturating_sub(offset); - self.scrollbase.drag(position); - } - Event::Mouse { - event: MouseEvent::Press(_), - position, - offset, - } => if let Some(position) = position.checked_sub(offset) { - let scrollbar_size = if self.scrollbase.scrollable() { - (2, 0) - } else { - (0, 0) - }; - let clickable_size = - self.last_size.saturating_sub(scrollbar_size); - if position < clickable_size { - fix_scroll = false; - let focus = position.y + self.scrollbase.start_line; - if focus < self.len() { - // Only select actual items - self.focus.set(focus); - } - } - }, Event::Mouse { event: MouseEvent::Release(MouseButton::Left), position, offset, - } => { - fix_scroll = false; - self.scrollbase.release_grab(); - if self.on_submit.is_some() { - if let Some(position) = position.checked_sub(offset) { - let scrollbar_size = if self.scrollbase.scrollable() { - (2, 0) - } else { - (0, 0) - }; - let clickable_size = - self.last_size.saturating_sub(scrollbar_size); - if position < clickable_size - && (position.y + self.scrollbase.start_line) - == self.focus() - { - return self.submit(); - } - } - } + } + if self.on_submit.is_some() + && position + .checked_sub(offset) + .map(|position| { + position < self.last_size + && position.y == self.focus() + }) + .unwrap_or(false) => + { + return self.submit(); } Event::Key(Key::Enter) if self.on_submit.is_some() => { return self.submit(); @@ -551,10 +481,6 @@ impl SelectView { } _ => return EventResult::Ignored, } - if fix_scroll { - let focus = self.focus(); - self.scrollbase.scroll_to(focus); - } EventResult::Consumed(self.make_select_cb()) } @@ -697,6 +623,8 @@ impl View for SelectView { self.last_offset.set(printer.offset); if self.popup { + // Popup-select only draw the active element. + // We'll draw the full list in a popup if needed. let style = if !self.enabled { ColorStyle::secondary() } else if !printer.focused { @@ -724,26 +652,30 @@ impl View for SelectView { printer.print((offset, 0), label); }); } else { + // Non-popup mode: we always print the entire list. let h = self.items.len(); let offset = self.align.v.get_offset(h, printer.size.y); let printer = &printer.offset((0, offset)); - self.scrollbase.draw(printer, |printer, i| { - printer.with_selection(i == self.focus(), |printer| { - if i != self.focus() && !self.enabled { - printer - .with_color(ColorStyle::secondary(), |printer| { - self.draw_item(printer, i) - }); - } else { - self.draw_item(printer, i); - } - }); - }); + for i in 0..self.len() { + printer.offset((0, i)).with_selection( + i == self.focus(), + |printer| { + if i != self.focus() && !self.enabled { + printer.with_color( + ColorStyle::secondary(), + |printer| self.draw_item(printer, i), + ); + } else { + self.draw_item(printer, i); + } + }, + ); + } } } - fn required_size(&mut self, req: Vec2) -> Vec2 { + fn required_size(&mut self, _: Vec2) -> Vec2 { // Items here are not compressible. // So no matter what the horizontal requirements are, // we'll still return our longest item. @@ -758,14 +690,7 @@ impl View for SelectView { } else { let h = self.items.len(); - let scrolling = req.y < h; - - // Add 2 spaces for the scrollbar if we need - let w = if scrolling { w + 2 } else { w }; - - // Don't request more than we're offered - we can scroll, - // after all - Vec2::new(w, min(h, req.y)) + Vec2::new(w, h) } } @@ -783,10 +708,6 @@ impl View for SelectView { fn layout(&mut self, size: Vec2) { self.last_size = size; - - if !self.popup { - self.scrollbase.set_heights(size.y, self.items.len()); - } } fn important_area(&self, size: Vec2) -> Rect {