Don't drag scrollbars if they're not visible

This commit is contained in:
Alexandre Bury 2018-06-20 17:35:58 -07:00
parent 2935f0f569
commit bd78bca91b
3 changed files with 38 additions and 13 deletions

View File

@ -89,18 +89,19 @@ impl InputParser {
if ncurses::getmouse(&mut mevent as *mut ncurses::MEVENT) if ncurses::getmouse(&mut mevent as *mut ncurses::MEVENT)
== ncurses::OK == ncurses::OK
{ {
// eprintln!("{:032b}", mevent.bstate);
// Currently unused // Currently unused
let _ctrl = (mevent.bstate & ncurses::BUTTON_CTRL as mmask_t) != 0;
let _shift = let _shift =
(mevent.bstate & ncurses::BUTTON_SHIFT as mmask_t) != 0; (mevent.bstate & ncurses::BUTTON_SHIFT as mmask_t) != 0;
let _alt = (mevent.bstate & ncurses::BUTTON_ALT as mmask_t) != 0; let _alt = (mevent.bstate & ncurses::BUTTON_ALT as mmask_t) != 0;
let _ctrl = (mevent.bstate & ncurses::BUTTON_CTRL as mmask_t) != 0;
// Keep the base state, without the modifiers
mevent.bstate &= !(ncurses::BUTTON_SHIFT mevent.bstate &= !(ncurses::BUTTON_SHIFT
| ncurses::BUTTON_ALT | ncurses::BUTTON_ALT
| ncurses::BUTTON_CTRL) | ncurses::BUTTON_CTRL)
as mmask_t; as mmask_t;
// This makes a full `Event` from a `MouseEvent`.
let make_event = |event| Event::Mouse { let make_event = |event| Event::Mouse {
offset: Vec2::zero(), offset: Vec2::zero(),
position: Vec2::new(mevent.x as usize, mevent.y as usize), position: Vec2::new(mevent.x as usize, mevent.y as usize),

View File

@ -189,7 +189,11 @@ where
/// Returns the size available for the child view. /// Returns the size available for the child view.
fn available_size(&self) -> Vec2 { fn available_size(&self) -> Vec2 {
self.last_size.saturating_sub(self.scrollbar_size()) if self.show_scrollbars {
self.last_size.saturating_sub(self.scrollbar_size())
} else {
self.last_size
}
} }
/// Compute the size we would need. /// Compute the size we would need.
@ -231,20 +235,21 @@ where
/// ///
/// Returns `true` if the event was consumed. /// Returns `true` if the event was consumed.
fn start_drag(&mut self, position: Vec2) -> bool { fn start_drag(&mut self, position: Vec2) -> bool {
// For each scrollbar, how far it is.
let scrollbar_pos = self.last_size.saturating_sub((1, 1)); let scrollbar_pos = self.last_size.saturating_sub((1, 1));
let grabbed = scrollbar_pos.zip_map(position, |s, p| s == p); // This is true for Y if we grabbed the vertical scrollbar
let grabbed = scrollbar_pos.zip_map(position, |s, p| s == p).swap();
let lengths = self.scrollbar_thumb_lengths(); let lengths = self.scrollbar_thumb_lengths();
let offsets = self.scrollbar_thumb_offsets(lengths); let offsets = self.scrollbar_thumb_offsets(lengths);
// See if we grabbed one of the scrollbars // Iterate on axises, and keep the one we grabbed.
for (orientation, pos, length, offset) in for (orientation, pos, length, offset) in
XY::zip4(Orientation::pair(), position, lengths, offsets) XY::zip4(Orientation::pair(), position, lengths, offsets)
.zip(grabbed.swap()) .keep(grabbed.and(self.enabled))
.into_iter() .into_iter()
.filter(|&(_, grab)| grab) .filter_map(|x| x)
.map(|(x, _)| x)
{ {
if pos >= offset && pos < offset + length { if pos >= offset && pos < offset + length {
// We grabbed the thumb! Now scroll from that position. // We grabbed the thumb! Now scroll from that position.
@ -262,7 +267,9 @@ where
false false
} }
/// Called when a mouse drag is detected.
fn drag(&mut self, position: Vec2) { fn drag(&mut self, position: Vec2) {
// Only do something if we grabbed something before.
if let Some((orientation, grab)) = self.thumb_grab { if let Some((orientation, grab)) = self.thumb_grab {
self.scroll_to_thumb( self.scroll_to_thumb(
orientation, orientation,
@ -466,10 +473,11 @@ where
event: MouseEvent::Press(MouseButton::Left), event: MouseEvent::Press(MouseButton::Left),
position, position,
offset, offset,
} if position } if self.show_scrollbars
.checked_sub(offset) && position
.map(|position| self.start_drag(position)) .checked_sub(offset)
.unwrap_or(false) => .map(|position| self.start_drag(position))
.unwrap_or(false) =>
{ {
// Just consume the event. // Just consume the event.
} }
@ -477,7 +485,8 @@ where
event: MouseEvent::Hold(MouseButton::Left), event: MouseEvent::Hold(MouseButton::Left),
position, position,
offset, offset,
} => { } if self.show_scrollbars =>
{
let position = position.saturating_sub(offset); let position = position.saturating_sub(offset);
self.drag(position); self.drag(position);
} }

View File

@ -140,6 +140,11 @@ impl<T> XY<T> {
{ {
XY::new(f(self.x, other.x), f(self.y, other.y)) XY::new(f(self.x, other.x), f(self.y, other.y))
} }
/// For each axis, keep the element from `self` if `keep` is `true`.
pub fn keep(self, keep: XY<bool>) -> XY<Option<T>> {
keep.select(self)
}
} }
impl<T: Clone> XY<T> { impl<T: Clone> XY<T> {
@ -192,6 +197,16 @@ impl XY<bool> {
pub fn select_or<T>(&self, if_true: XY<T>, if_false: XY<T>) -> XY<T> { pub fn select_or<T>(&self, if_true: XY<T>, if_false: XY<T>) -> XY<T> {
self.select(if_true).unwrap_or(if_false) self.select(if_true).unwrap_or(if_false)
} }
/// Returns a term-by-term AND operation.
pub fn and(&self, other: Self) -> Self {
self.zip_map(other, |s, o| s && o)
}
/// Returns a term-by-term OR operation.
pub fn or(&self, other: Self) -> Self {
self.zip_map(other, |s, o| s || o)
}
} }
impl<T: Copy> XY<T> { impl<T: Copy> XY<T> {