Do not notify the parent unintentionally
This commit is contained in:
parent
40084aa94c
commit
fd33832609
2 changed files with 83 additions and 37 deletions
|
@ -2504,7 +2504,7 @@ impl Window {
|
||||||
&mut self,
|
&mut self,
|
||||||
key: impl Into<ElementId>,
|
key: impl Into<ElementId>,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
|
init: impl FnOnce(&mut Self, &mut App) -> S,
|
||||||
) -> Entity<S> {
|
) -> Entity<S> {
|
||||||
let current_view = self.current_view();
|
let current_view = self.current_view();
|
||||||
self.with_global_id(key.into(), |global_id, window| {
|
self.with_global_id(key.into(), |global_id, window| {
|
||||||
|
@ -2537,7 +2537,7 @@ impl Window {
|
||||||
pub fn use_state<S: 'static>(
|
pub fn use_state<S: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
|
init: impl FnOnce(&mut Self, &mut App) -> S,
|
||||||
) -> Entity<S> {
|
) -> Entity<S> {
|
||||||
self.use_keyed_state(
|
self.use_keyed_state(
|
||||||
ElementId::CodeLocation(*core::panic::Location::caller()),
|
ElementId::CodeLocation(*core::panic::Location::caller()),
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::{fmt::Debug, marker::PhantomData, ops::Not, time::Duration};
|
use std::{fmt::Debug, marker::PhantomData, ops::Not, time::Duration};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Along, App, Axis as ScrollbarAxis, BorderStyle, Bounds, ContentMask, Context, Corner, Corners,
|
Along, App, AppContext as _, Axis as ScrollbarAxis, BorderStyle, Bounds, ContentMask, Context,
|
||||||
CursorStyle, Div, Edges, Element, ElementId, Entity, EntityId, GlobalElementId, Hitbox,
|
Corner, Corners, CursorStyle, Div, Edges, Element, ElementId, Entity, EntityId,
|
||||||
HitboxBehavior, Hsla, InteractiveElement, IntoElement, IsZero, LayoutId, ListState,
|
GlobalElementId, Hitbox, HitboxBehavior, Hsla, InteractiveElement, IntoElement, IsZero,
|
||||||
MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point,
|
LayoutId, ListState, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement,
|
||||||
Position, Render, ScrollHandle, ScrollWheelEvent, Size, Stateful, StatefulInteractiveElement,
|
Pixels, Point, Position, Render, ScrollHandle, ScrollWheelEvent, Size, Stateful,
|
||||||
Style, Styled, Task, UniformListScrollHandle, Window, prelude::FluentBuilder as _, px, quad,
|
StatefulInteractiveElement, Style, Styled, Task, UniformList, UniformListDecoration,
|
||||||
relative, size,
|
UniformListScrollHandle, Window, prelude::FluentBuilder as _, px, quad, relative, size,
|
||||||
};
|
};
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -92,6 +92,23 @@ pub mod scrollbars {
|
||||||
impl Global for ScrollbarAutoHide {}
|
impl Global for ScrollbarAutoHide {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_scrollbar_state<S, T>(
|
||||||
|
mut config: Scrollbars<S, T>,
|
||||||
|
caller_location: &'static std::panic::Location,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> Entity<ScrollbarStateWrapper<S, T>>
|
||||||
|
where
|
||||||
|
S: ScrollbarVisibilitySetting,
|
||||||
|
T: ScrollableHandle,
|
||||||
|
{
|
||||||
|
let element_id = config.id.take().unwrap_or_else(|| caller_location.into());
|
||||||
|
|
||||||
|
window.use_keyed_state(element_id, cx, |window, cx| {
|
||||||
|
ScrollbarStateWrapper(cx.new(|cx| ScrollbarState::new_from_config(config, window, cx)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub trait WithScrollbar: Sized {
|
pub trait WithScrollbar: Sized {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
@ -146,7 +163,7 @@ impl WithScrollbar for Stateful<Div> {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn custom_scrollbars<S, T>(
|
fn custom_scrollbars<S, T>(
|
||||||
self,
|
self,
|
||||||
mut config: Scrollbars<S, T>,
|
config: Scrollbars<S, T>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Self::Output
|
) -> Self::Output
|
||||||
|
@ -154,16 +171,11 @@ impl WithScrollbar for Stateful<Div> {
|
||||||
S: ScrollbarVisibilitySetting,
|
S: ScrollbarVisibilitySetting,
|
||||||
T: ScrollableHandle,
|
T: ScrollableHandle,
|
||||||
{
|
{
|
||||||
let element_id = config
|
render_scrollbar(
|
||||||
.id
|
get_scrollbar_state(config, std::panic::Location::caller(), window, cx),
|
||||||
.take()
|
self,
|
||||||
.unwrap_or_else(|| core::panic::Location::caller().into());
|
cx,
|
||||||
|
)
|
||||||
let scrollbar = window.use_keyed_state(element_id.clone(), cx, |window, cx| {
|
|
||||||
ScrollbarState::new_from_config(config, window, cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
render_scrollbar(scrollbar, self, cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +185,7 @@ impl WithScrollbar for Div {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn custom_scrollbars<S, T>(
|
fn custom_scrollbars<S, T>(
|
||||||
self,
|
self,
|
||||||
mut config: Scrollbars<S, T>,
|
config: Scrollbars<S, T>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Self::Output
|
) -> Self::Output
|
||||||
|
@ -181,14 +193,7 @@ impl WithScrollbar for Div {
|
||||||
S: ScrollbarVisibilitySetting,
|
S: ScrollbarVisibilitySetting,
|
||||||
T: ScrollableHandle,
|
T: ScrollableHandle,
|
||||||
{
|
{
|
||||||
let element_id = config
|
let scrollbar = get_scrollbar_state(config, std::panic::Location::caller(), window, cx);
|
||||||
.id
|
|
||||||
.take()
|
|
||||||
.unwrap_or_else(|| core::panic::Location::caller().into());
|
|
||||||
|
|
||||||
let scrollbar = window.use_keyed_state(element_id.clone(), cx, |window, cx| {
|
|
||||||
ScrollbarState::new_from_config(config, window, cx)
|
|
||||||
});
|
|
||||||
// We know this ID stays consistent as long as the element is rendered for
|
// We know this ID stays consistent as long as the element is rendered for
|
||||||
// consecutive frames, which is sufficient for our use case here
|
// consecutive frames, which is sufficient for our use case here
|
||||||
let scrollbar_entity_id = scrollbar.entity_id();
|
let scrollbar_entity_id = scrollbar.entity_id();
|
||||||
|
@ -202,7 +207,7 @@ impl WithScrollbar for Div {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_scrollbar<S, T>(
|
fn render_scrollbar<S, T>(
|
||||||
scrollbar: Entity<ScrollbarState<S, T>>,
|
scrollbar: Entity<ScrollbarStateWrapper<S, T>>,
|
||||||
div: Stateful<Div>,
|
div: Stateful<Div>,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Stateful<Div>
|
) -> Stateful<Div>
|
||||||
|
@ -210,28 +215,63 @@ where
|
||||||
S: ScrollbarVisibilitySetting,
|
S: ScrollbarVisibilitySetting,
|
||||||
T: ScrollableHandle,
|
T: ScrollableHandle,
|
||||||
{
|
{
|
||||||
if scrollbar.read(cx).disabled() {
|
let state = &scrollbar.read(cx).0;
|
||||||
|
|
||||||
|
if state.read(cx).disabled() {
|
||||||
div
|
div
|
||||||
} else {
|
} else {
|
||||||
div.when_some(scrollbar.read(cx).handle_to_track(), |this, handle| {
|
div.when_some(state.read(cx).handle_to_track(), |this, handle| {
|
||||||
this.track_scroll(handle)
|
this.track_scroll(handle)
|
||||||
})
|
})
|
||||||
.when_some(
|
.when_some(
|
||||||
scrollbar
|
state
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.space_to_reserve_for(ScrollbarAxis::Horizontal),
|
.space_to_reserve_for(ScrollbarAxis::Horizontal),
|
||||||
|this, space| this.pb(space),
|
|this, space| this.pb(space),
|
||||||
)
|
)
|
||||||
.when_some(
|
.when_some(
|
||||||
scrollbar
|
state.read(cx).space_to_reserve_for(ScrollbarAxis::Vertical),
|
||||||
.read(cx)
|
|
||||||
.space_to_reserve_for(ScrollbarAxis::Vertical),
|
|
||||||
|this, space| this.pr(space),
|
|this, space| this.pr(space),
|
||||||
)
|
)
|
||||||
.child(scrollbar)
|
.child(state.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> UniformListDecoration
|
||||||
|
// for ScrollbarState<S, T>
|
||||||
|
// {
|
||||||
|
// fn compute(
|
||||||
|
// &self,
|
||||||
|
// visible_range: Range<usize>,
|
||||||
|
// bounds: Bounds<Pixels>,
|
||||||
|
// scroll_offset: Point<Pixels>,
|
||||||
|
// item_height: Pixels,
|
||||||
|
// item_count: usize,
|
||||||
|
// window: &mut Window,
|
||||||
|
// cx: &mut App,
|
||||||
|
// ) -> gpui::AnyElement {
|
||||||
|
// let element = ScrollbarElement::new(self);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl WithScrollbar for UniformList {
|
||||||
|
// type Output = Self;
|
||||||
|
|
||||||
|
// fn custom_scrollbars<S, T>(
|
||||||
|
// self,
|
||||||
|
// config: Scrollbars<S, T>,
|
||||||
|
// window: &mut Window,
|
||||||
|
// cx: &mut App,
|
||||||
|
// ) -> Self::Output
|
||||||
|
// where
|
||||||
|
// S: ScrollbarVisibilitySetting,
|
||||||
|
// T: ScrollableHandle,
|
||||||
|
// {
|
||||||
|
// let scrollbar = get_scrollbar_state(config, std::panic::Location::caller(), window, cx);
|
||||||
|
// self.with_decoration(scrollbar)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub enum ScrollAxes {
|
pub enum ScrollAxes {
|
||||||
Horizontal,
|
Horizontal,
|
||||||
|
@ -417,6 +457,12 @@ impl VisibilityState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is used to ensure notifies within the state do not notify the parent
|
||||||
|
/// unintentionally.
|
||||||
|
struct ScrollbarStateWrapper<S: ScrollbarVisibilitySetting, T: ScrollableHandle>(
|
||||||
|
Entity<ScrollbarState<S, T>>,
|
||||||
|
);
|
||||||
|
|
||||||
/// A scrollbar state that should be persisted across frames.
|
/// A scrollbar state that should be persisted across frames.
|
||||||
struct ScrollbarState<S: ScrollbarVisibilitySetting, T: ScrollableHandle = ScrollHandle> {
|
struct ScrollbarState<S: ScrollbarVisibilitySetting, T: ScrollableHandle = ScrollHandle> {
|
||||||
thumb_state: ThumbState,
|
thumb_state: ThumbState,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue