WIP
This commit is contained in:
parent
d705585a2e
commit
c28d873a2f
34 changed files with 1295 additions and 2348 deletions
|
@ -11,17 +11,17 @@ use editor::{
|
|||
use gpui::{
|
||||
Action, AnyElement, App, ClickEvent, Context, DismissEvent, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, Length, ListSizingBehavior, ListState, MouseButton, MouseUpEvent, Render,
|
||||
ScrollStrategy, Stateful, Task, UniformListScrollHandle, Window, actions, div, list,
|
||||
prelude::*, uniform_list,
|
||||
ScrollStrategy, Task, UniformListScrollHandle, Window, actions, div, list, prelude::*,
|
||||
uniform_list,
|
||||
};
|
||||
use head::Head;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use std::{ops::Range, sync::Arc, time::Duration};
|
||||
use ui::{
|
||||
Color, Divider, Label, ListItem, ListItemSpacing, Scrollbar, ScrollbarState, prelude::*, v_flex,
|
||||
Color, Divider, Label, ListItem, ListItemSpacing, ScrollAxes, Scrollbars, WithScrollbar,
|
||||
prelude::*, v_flex,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::ModalView;
|
||||
|
||||
enum ElementContainer {
|
||||
|
@ -65,13 +65,8 @@ pub struct Picker<D: PickerDelegate> {
|
|||
width: Option<Length>,
|
||||
widest_item: Option<usize>,
|
||||
max_height: Option<Length>,
|
||||
focus_handle: FocusHandle,
|
||||
/// An external control to display a scrollbar in the `Picker`.
|
||||
show_scrollbar: bool,
|
||||
/// An internal state that controls whether to show the scrollbar based on the user's focus.
|
||||
scrollbar_visibility: bool,
|
||||
scrollbar_state: ScrollbarState,
|
||||
hide_scrollbar_task: Option<Task<()>>,
|
||||
/// Whether the `Picker` is rendered as a self-contained modal.
|
||||
///
|
||||
/// Set this to `false` when rendering the `Picker` as part of a larger modal.
|
||||
|
@ -293,13 +288,6 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let element_container = Self::create_element_container(container);
|
||||
let scrollbar_state = match &element_container {
|
||||
ElementContainer::UniformList(scroll_handle) => {
|
||||
ScrollbarState::new(scroll_handle.clone())
|
||||
}
|
||||
ElementContainer::List(state) => ScrollbarState::new(state.clone()),
|
||||
};
|
||||
let focus_handle = cx.focus_handle();
|
||||
let mut this = Self {
|
||||
delegate,
|
||||
head,
|
||||
|
@ -309,12 +297,8 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
width: None,
|
||||
widest_item: None,
|
||||
max_height: Some(rems(18.).into()),
|
||||
focus_handle,
|
||||
show_scrollbar: false,
|
||||
scrollbar_visibility: true,
|
||||
scrollbar_state,
|
||||
is_modal: true,
|
||||
hide_scrollbar_task: None,
|
||||
};
|
||||
this.update_matches("".to_string(), window, cx);
|
||||
// give the delegate 4ms to render the first set of suggestions.
|
||||
|
@ -790,67 +774,6 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn hide_scrollbar(&mut self, cx: &mut Context<Self>) {
|
||||
const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
|
||||
self.hide_scrollbar_task = Some(cx.spawn(async move |panel, cx| {
|
||||
cx.background_executor()
|
||||
.timer(SCROLLBAR_SHOW_INTERVAL)
|
||||
.await;
|
||||
panel
|
||||
.update(cx, |panel, cx| {
|
||||
panel.scrollbar_visibility = false;
|
||||
cx.notify();
|
||||
})
|
||||
.log_err();
|
||||
}))
|
||||
}
|
||||
|
||||
fn render_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
|
||||
if !self.show_scrollbar
|
||||
|| !(self.scrollbar_visibility || self.scrollbar_state.is_dragging())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(
|
||||
div()
|
||||
.occlude()
|
||||
.id("picker-scroll")
|
||||
.h_full()
|
||||
.absolute()
|
||||
.right_1()
|
||||
.top_1()
|
||||
.bottom_0()
|
||||
.w(px(12.))
|
||||
.cursor_default()
|
||||
.on_mouse_move(cx.listener(|_, _, _window, cx| {
|
||||
cx.notify();
|
||||
cx.stop_propagation()
|
||||
}))
|
||||
.on_hover(|_, _window, cx| {
|
||||
cx.stop_propagation();
|
||||
})
|
||||
.on_any_mouse_down(|_, _window, cx| {
|
||||
cx.stop_propagation();
|
||||
})
|
||||
.on_mouse_up(
|
||||
MouseButton::Left,
|
||||
cx.listener(|picker, _, window, cx| {
|
||||
if !picker.scrollbar_state.is_dragging()
|
||||
&& !picker.focus_handle.contains_focused(window, cx)
|
||||
{
|
||||
picker.hide_scrollbar(cx);
|
||||
cx.notify();
|
||||
}
|
||||
cx.stop_propagation();
|
||||
}),
|
||||
)
|
||||
.on_scroll_wheel(cx.listener(|_, _, _window, cx| {
|
||||
cx.notify();
|
||||
}))
|
||||
.children(Scrollbar::vertical(self.scrollbar_state.clone())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: PickerDelegate> EventEmitter<DismissEvent> for Picker<D> {}
|
||||
|
@ -900,17 +823,12 @@ impl<D: PickerDelegate> Render for Picker<D> {
|
|||
.overflow_hidden()
|
||||
.children(self.delegate.render_header(window, cx))
|
||||
.child(self.render_element_container(cx))
|
||||
.on_hover(cx.listener(|this, hovered, window, cx| {
|
||||
if *hovered {
|
||||
this.scrollbar_visibility = true;
|
||||
this.hide_scrollbar_task.take();
|
||||
cx.notify();
|
||||
} else if !this.focus_handle.contains_focused(window, cx) {
|
||||
this.hide_scrollbar(cx);
|
||||
}
|
||||
}))
|
||||
.when_some(self.render_scrollbar(cx), |div, scrollbar| {
|
||||
div.child(scrollbar)
|
||||
.when(self.show_scrollbar, |this| {
|
||||
this.custom_scrollbars(
|
||||
Scrollbars::new(ScrollAxes::Vertical).width_sm(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue