Support scrolling popup contents using mouse (#10053)

* Extract popup scrolling code into named functions

* Scroll popup contents on mouse scroll event

* Ignore mouse events outside the popup

* Remove unneeded return statement
pull/10064/head
Gokul Soumya 3 months ago committed by GitHub
parent 0da5865695
commit 957d030be9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -11,6 +11,7 @@ use tui::{
use helix_core::Position; use helix_core::Position;
use helix_view::{ use helix_view::{
graphics::{Margin, Rect}, graphics::{Margin, Rect},
input::{MouseEvent, MouseEventKind},
Editor, Editor,
}; };
@ -23,6 +24,7 @@ pub struct Popup<T: Component> {
margin: Margin, margin: Margin,
size: (u16, u16), size: (u16, u16),
child_size: (u16, u16), child_size: (u16, u16),
area: Rect,
position_bias: Open, position_bias: Open,
scroll: usize, scroll: usize,
auto_close: bool, auto_close: bool,
@ -40,6 +42,7 @@ impl<T: Component> Popup<T> {
size: (0, 0), size: (0, 0),
position_bias: Open::Below, position_bias: Open::Below,
child_size: (0, 0), child_size: (0, 0),
area: Rect::new(0, 0, 0, 0),
scroll: 0, scroll: 0,
auto_close: false, auto_close: false,
ignore_escape_key: false, ignore_escape_key: false,
@ -146,6 +149,14 @@ impl<T: Component> Popup<T> {
} }
} }
pub fn scroll_half_page_down(&mut self) {
self.scroll(self.size.1 as usize / 2, true)
}
pub fn scroll_half_page_up(&mut self) {
self.scroll(self.size.1 as usize / 2, false)
}
/// Toggles the Popup's scrollbar. /// Toggles the Popup's scrollbar.
/// Consider disabling the scrollbar in case the child /// Consider disabling the scrollbar in case the child
/// already has its own. /// already has its own.
@ -171,12 +182,44 @@ impl<T: Component> Popup<T> {
// clip to viewport // clip to viewport
viewport.intersection(Rect::new(rel_x, rel_y, self.size.0, self.size.1)) viewport.intersection(Rect::new(rel_x, rel_y, self.size.0, self.size.1))
} }
fn handle_mouse_event(
&mut self,
&MouseEvent {
kind,
column: x,
row: y,
..
}: &MouseEvent,
) -> EventResult {
let mouse_is_within_popup = x >= self.area.left()
&& x < self.area.right()
&& y >= self.area.top()
&& y < self.area.bottom();
if !mouse_is_within_popup {
return EventResult::Ignored(None);
}
match kind {
MouseEventKind::ScrollDown if self.has_scrollbar => {
self.scroll_half_page_down();
EventResult::Consumed(None)
}
MouseEventKind::ScrollUp if self.has_scrollbar => {
self.scroll_half_page_up();
EventResult::Consumed(None)
}
_ => EventResult::Ignored(None),
}
}
} }
impl<T: Component> Component for Popup<T> { impl<T: Component> Component for Popup<T> {
fn handle_event(&mut self, event: &Event, cx: &mut Context) -> EventResult { fn handle_event(&mut self, event: &Event, cx: &mut Context) -> EventResult {
let key = match event { let key = match event {
Event::Key(event) => *event, Event::Key(event) => *event,
Event::Mouse(event) => return self.handle_mouse_event(event),
Event::Resize(_, _) => { Event::Resize(_, _) => {
// TODO: calculate inner area, call component's handle_event with that area // TODO: calculate inner area, call component's handle_event with that area
return EventResult::Ignored(None); return EventResult::Ignored(None);
@ -200,11 +243,11 @@ impl<T: Component> Component for Popup<T> {
EventResult::Consumed(Some(close_fn)) EventResult::Consumed(Some(close_fn))
} }
ctrl!('d') => { ctrl!('d') => {
self.scroll(self.size.1 as usize / 2, true); self.scroll_half_page_down();
EventResult::Consumed(None) EventResult::Consumed(None)
} }
ctrl!('u') => { ctrl!('u') => {
self.scroll(self.size.1 as usize / 2, false); self.scroll_half_page_up();
EventResult::Consumed(None) EventResult::Consumed(None)
} }
_ => { _ => {
@ -249,6 +292,7 @@ impl<T: Component> Component for Popup<T> {
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) {
let area = self.area(viewport, cx.editor); let area = self.area(viewport, cx.editor);
self.area = area;
cx.scroll = Some(self.scroll); cx.scroll = Some(self.scroll);
// clear area // clear area

Loading…
Cancel
Save