editor: Add scrollbar to info popovers (#20184)
Related to https://github.com/zed-industries/zed/issues/5034 Release Notes: - Added scrollbar to info popovers in editor.
This commit is contained in:
parent
966b18e142
commit
dc02894db4
2 changed files with 62 additions and 21 deletions
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue