@@ -7,7 +7,7 @@ use crate::{
};
use gpui::{
div, px, AnyElement, AsyncWindowContext, FontWeight, Hsla, InteractiveElement, IntoElement,
- MouseButton, ParentElement, Pixels, ScrollHandle, Size, StatefulInteractiveElement,
+ MouseButton, ParentElement, Pixels, ScrollHandle, Size, Stateful, StatefulInteractiveElement,
StyleRefinement, Styled, Task, TextStyleRefinement, View, ViewContext,
};
use itertools::Itertools;
@@ -21,7 +21,7 @@ use std::rc::Rc;
use std::{borrow::Cow, cell::RefCell};
use std::{ops::Range, sync::Arc, time::Duration};
use theme::ThemeSettings;
-use ui::{prelude::*, window_is_transparent};
+use ui::{prelude::*, window_is_transparent, Scrollbar, ScrollbarState};
use util::TryFutureExt;
pub const HOVER_DELAY_MILLIS: u64 = 350;
pub const HOVER_REQUEST_DELAY_MILLIS: u64 = 200;
@@ -144,10 +144,12 @@ pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut Vie
let blocks = vec![inlay_hover.tooltip];
let parsed_content = parse_blocks(&blocks, &language_registry, None, &mut cx).await;
+ let scroll_handle = ScrollHandle::new();
let hover_popover = InfoPopover {
symbol_range: RangeInEditor::Inlay(inlay_hover.range.clone()),
parsed_content,
- scroll_handle: ScrollHandle::new(),
+ scrollbar_state: ScrollbarState::new(scroll_handle.clone()),
+ scroll_handle,
keyboard_grace: Rc::new(RefCell::new(false)),
anchor: None,
};
@@ -435,12 +437,14 @@ fn show_hover(
let language = hover_result.language;
let parsed_content =
parse_blocks(&blocks, &language_registry, language, &mut cx).await;
+ let scroll_handle = ScrollHandle::new();
info_popover_tasks.push((
range.clone(),
InfoPopover {
symbol_range: RangeInEditor::Text(range),
parsed_content,
- scroll_handle: ScrollHandle::new(),
+ scrollbar_state: ScrollbarState::new(scroll_handle.clone()),
+ scroll_handle,
keyboard_grace: Rc::new(RefCell::new(ignore_timeout)),
anchor: Some(anchor),
},
@@ -680,13 +684,13 @@ impl HoverState {
}
#[derive(Debug, Clone)]
-
-pub struct InfoPopover {
- pub symbol_range: RangeInEditor,
- pub parsed_content: Option<View<Markdown>>,
- pub scroll_handle: ScrollHandle,
- pub keyboard_grace: Rc<RefCell<bool>>,
- pub anchor: Option<Anchor>,
+pub(crate) struct InfoPopover {
+ pub(crate) symbol_range: RangeInEditor,
+ pub(crate) parsed_content: Option<View<Markdown>>,
+ pub(crate) scroll_handle: ScrollHandle,
+ pub(crate) scrollbar_state: ScrollbarState,
+ pub(crate) keyboard_grace: Rc<RefCell<bool>>,
+ pub(crate) anchor: Option<Anchor>,
}
impl InfoPopover {
@@ -695,10 +699,6 @@ impl InfoPopover {
let mut d = div()
.id("info_popover")
.elevation_2(cx)
- .overflow_y_scroll()
- .track_scroll(&self.scroll_handle)
- .max_w(max_size.width)
- .max_h(max_size.height)
// Prevent a mouse down/move on the popover from being propagated to the editor,
// because that would dismiss the popover.
.on_mouse_move(|_, cx| cx.stop_propagation())
@@ -706,11 +706,21 @@ impl InfoPopover {
let mut keyboard_grace = keyboard_grace.borrow_mut();
*keyboard_grace = false;
cx.stop_propagation();
- })
- .p_2();
+ });
if let Some(markdown) = &self.parsed_content {
- d = d.child(markdown.clone());
+ d = d
+ .child(
+ div()
+ .id("info-md-container")
+ .overflow_y_scroll()
+ .max_w(max_size.width)
+ .max_h(max_size.height)
+ .p_2()
+ .track_scroll(&self.scroll_handle)
+ .child(markdown.clone()),
+ )
+ .child(self.render_vertical_scrollbar(cx));
}
d.into_any_element()
}
@@ -724,6 +734,38 @@ impl InfoPopover {
cx.notify();
self.scroll_handle.set_offset(current);
}
+ fn render_vertical_scrollbar(&self, cx: &mut ViewContext<Editor>) -> Stateful<Div> {
+ div()
+ .occlude()
+ .id("info-popover-vertical-scroll")
+ .on_mouse_move(cx.listener(|_, _, cx| {
+ cx.notify();
+ cx.stop_propagation()
+ }))
+ .on_hover(|_, cx| {
+ cx.stop_propagation();
+ })
+ .on_any_mouse_down(|_, cx| {
+ cx.stop_propagation();
+ })
+ .on_mouse_up(
+ MouseButton::Left,
+ cx.listener(|_, _, cx| {
+ cx.stop_propagation();
+ }),
+ )
+ .on_scroll_wheel(cx.listener(|_, _, cx| {
+ cx.notify();
+ }))
+ .h_full()
+ .absolute()
+ .right_1()
+ .top_1()
+ .bottom_0()
+ .w(px(12.))
+ .cursor_default()
+ .children(Scrollbar::vertical(self.scrollbar_state.clone()))
+ }
}
#[derive(Debug, Clone)]
@@ -16,7 +16,7 @@ pub struct Scrollbar {
}
/// Wrapper around scroll handles.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub enum ScrollableHandle {
Uniform(UniformListScrollHandle),
NonUniform(ScrollHandle),
@@ -91,7 +91,7 @@ impl From<ScrollHandle> for ScrollableHandle {
}
/// A scrollbar state that should be persisted across frames.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct ScrollbarState {
// If Some(), there's an active drag, offset by percentage from the origin of a thumb.
drag: Rc<Cell<Option<f32>>>,
@@ -142,7 +142,6 @@ impl ScrollbarState {
}
let mut percentage = current_offset / main_dimension_size;
let viewport_size = self.scroll_handle.viewport().size;
-
let end_offset = (current_offset + viewport_size.along(axis).0) / main_dimension_size;
// Scroll handle might briefly report an offset greater than the length of a list;
// in such case we'll adjust the starting offset as well to keep the scrollbar thumb length stable.