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)
== ncurses::OK
{
// eprintln!("{:032b}", mevent.bstate);
// Currently unused
let _ctrl = (mevent.bstate & ncurses::BUTTON_CTRL as mmask_t) != 0;
let _shift =
(mevent.bstate & ncurses::BUTTON_SHIFT 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
| ncurses::BUTTON_ALT
| ncurses::BUTTON_CTRL)
as mmask_t;
// This makes a full `Event` from a `MouseEvent`.
let make_event = |event| Event::Mouse {
offset: Vec2::zero(),
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.
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.
@ -231,20 +235,21 @@ where
///
/// Returns `true` if the event was consumed.
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 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 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
XY::zip4(Orientation::pair(), position, lengths, offsets)
.zip(grabbed.swap())
.keep(grabbed.and(self.enabled))
.into_iter()
.filter(|&(_, grab)| grab)
.map(|(x, _)| x)
.filter_map(|x| x)
{
if pos >= offset && pos < offset + length {
// We grabbed the thumb! Now scroll from that position.
@ -262,7 +267,9 @@ where
false
}
/// Called when a mouse drag is detected.
fn drag(&mut self, position: Vec2) {
// Only do something if we grabbed something before.
if let Some((orientation, grab)) = self.thumb_grab {
self.scroll_to_thumb(
orientation,
@ -466,10 +473,11 @@ where
event: MouseEvent::Press(MouseButton::Left),
position,
offset,
} if position
.checked_sub(offset)
.map(|position| self.start_drag(position))
.unwrap_or(false) =>
} if self.show_scrollbars
&& position
.checked_sub(offset)
.map(|position| self.start_drag(position))
.unwrap_or(false) =>
{
// Just consume the event.
}
@ -477,7 +485,8 @@ where
event: MouseEvent::Hold(MouseButton::Left),
position,
offset,
} => {
} if self.show_scrollbars =>
{
let position = position.saturating_sub(offset);
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))
}
/// 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> {
@ -192,6 +197,16 @@ impl XY<bool> {
pub fn select_or<T>(&self, if_true: XY<T>, if_false: XY<T>) -> XY<T> {
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> {