Impl for uniformlist and notify cleanupds

This commit is contained in:
MrSubidubi 2025-08-14 17:22:55 +02:00
parent fd33832609
commit a9dbfce8f9
2 changed files with 91 additions and 52 deletions

View file

@ -5,10 +5,10 @@
//! elements with uniform height. //! elements with uniform height.
use crate::{ use crate::{
AnyElement, App, AvailableSpace, Bounds, ContentMask, Element, ElementId, GlobalElementId, AnyElement, App, AvailableSpace, Bounds, ContentMask, Element, ElementId, Entity,
Hitbox, InspectorElementId, InteractiveElement, Interactivity, IntoElement, IsZero, LayoutId, GlobalElementId, Hitbox, InspectorElementId, InteractiveElement, Interactivity, IntoElement,
ListSizingBehavior, Overflow, Pixels, Point, ScrollHandle, Size, StyleRefinement, Styled, IsZero, LayoutId, ListSizingBehavior, Overflow, Pixels, Point, ScrollHandle, Size,
Window, point, size, StyleRefinement, Styled, Window, point, size,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
@ -71,7 +71,7 @@ pub struct UniformList {
/// Frame state used by the [UniformList]. /// Frame state used by the [UniformList].
pub struct UniformListFrameState { pub struct UniformListFrameState {
items: SmallVec<[AnyElement; 32]>, items: SmallVec<[AnyElement; 32]>,
decorations: SmallVec<[AnyElement; 1]>, decorations: SmallVec<[AnyElement; 2]>,
} }
/// A handle for controlling the scroll position of a uniform list. /// A handle for controlling the scroll position of a uniform list.
@ -529,6 +529,31 @@ pub trait UniformListDecoration {
) -> AnyElement; ) -> AnyElement;
} }
impl<T: UniformListDecoration + 'static> UniformListDecoration for Entity<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,
) -> AnyElement {
self.update(cx, |inner, cx| {
inner.compute(
visible_range,
bounds,
scroll_offset,
item_height,
item_count,
window,
cx,
)
})
}
}
impl UniformList { impl UniformList {
/// Selects a specific list item for measurement. /// Selects a specific list item for measurement.
pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self { pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self {

View file

@ -237,40 +237,43 @@ where
} }
} }
// impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> UniformListDecoration impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> UniformListDecoration
// for ScrollbarState<S, T> for ScrollbarStateWrapper<S, T>
// { {
// fn compute( fn compute(
// &self, &self,
// visible_range: Range<usize>, _visible_range: Range<usize>,
// bounds: Bounds<Pixels>, _bounds: Bounds<Pixels>,
// scroll_offset: Point<Pixels>, _scroll_offset: Point<Pixels>,
// item_height: Pixels, _item_height: Pixels,
// item_count: usize, _item_count: usize,
// window: &mut Window, _window: &mut Window,
// cx: &mut App, _cx: &mut App,
// ) -> gpui::AnyElement { ) -> gpui::AnyElement {
// let element = ScrollbarElement::new(self); ScrollbarElement {
// } state: self.0.clone(),
// } }
.into_any()
}
}
// impl WithScrollbar for UniformList { impl WithScrollbar for UniformList {
// type Output = Self; type Output = Self;
// fn custom_scrollbars<S, T>( fn custom_scrollbars<S, T>(
// self, self,
// config: Scrollbars<S, T>, config: Scrollbars<S, T>,
// window: &mut Window, window: &mut Window,
// cx: &mut App, cx: &mut App,
// ) -> Self::Output ) -> Self::Output
// where where
// S: ScrollbarVisibilitySetting, S: ScrollbarVisibilitySetting,
// T: ScrollableHandle, T: ScrollableHandle,
// { {
// let scrollbar = get_scrollbar_state(config, std::panic::Location::caller(), window, cx); let scrollbar = get_scrollbar_state(config, std::panic::Location::caller(), window, cx);
// self.with_decoration(scrollbar) self.with_decoration(scrollbar)
// } }
// } }
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
pub enum ScrollAxes { pub enum ScrollAxes {
@ -568,6 +571,16 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
&self.scroll_handle &self.scroll_handle
} }
fn set_offset(&mut self, offset: Point<Pixels>, cx: &mut Context<Self>) {
if self.scroll_handle.offset() != offset {
self.scroll_handle.set_offset(offset);
self.notify_parent(cx);
}
// We always want to show scrollbars in cases where the offset is updated.
self.show_scrollbars(cx);
}
fn is_dragging(&self) -> bool { fn is_dragging(&self) -> bool {
self.thumb_state.is_dragging() self.thumb_state.is_dragging()
} }
@ -1044,7 +1057,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
if thumb_bounds.contains(&event.position) { if thumb_bounds.contains(&event.position) {
let offset = let offset =
event.position.along(*axis) - thumb_bounds.origin.along(*axis); event.position.along(*axis) - thumb_bounds.origin.along(*axis);
state.set_dragging(*axis, offset, cx) state.set_dragging(*axis, offset, cx);
} else { } else {
let scroll_handle = state.scroll_handle(); let scroll_handle = state.scroll_handle();
let click_offset = scrollbar_layout.compute_click_offset( let click_offset = scrollbar_layout.compute_click_offset(
@ -1052,12 +1065,13 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
scroll_handle.max_offset(), scroll_handle.max_offset(),
ScrollbarMouseEvent::TrackClick, ScrollbarMouseEvent::TrackClick,
); );
scroll_handle.set_offset( state.set_offset(
scroll_handle.offset().apply_along(*axis, |_| click_offset), scroll_handle.offset().apply_along(*axis, |_| click_offset),
cx,
); );
};
cx.stop_propagation(); cx.stop_propagation();
}
}); });
} }
}); });
@ -1071,10 +1085,14 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
{ {
let scroll_handle = state.read(cx).scroll_handle(); let scroll_handle = state.read(cx).scroll_handle();
let current_offset = scroll_handle.offset(); let current_offset = scroll_handle.offset();
scroll_handle.set_offset( state.update(cx, |state, cx| {
current_offset + event.delta.pixel_delta(window.line_height()), state.set_offset(
); current_offset + event.delta.pixel_delta(window.line_height()),
state.update(cx, |state, cx| state.show_scrollbars(cx)); cx,
);
state.show_scrollbars(cx);
cx.stop_propagation();
});
} }
} }
}); });
@ -1096,13 +1114,10 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
scroll_handle.max_offset(), scroll_handle.max_offset(),
ScrollbarMouseEvent::ThumbDrag(drag_state), ScrollbarMouseEvent::ThumbDrag(drag_state),
); );
scroll_handle.set_offset( let new_offset =
scroll_handle.offset().apply_along(axis, |_| drag_offset), scroll_handle.offset().apply_along(axis, |_| drag_offset);
);
// todo! Needed? state.update(cx, |state, cx| state.set_offset(new_offset, cx));
window.refresh();
state.update(cx, |state, cx| state.notify_parent(cx));
cx.stop_propagation(); cx.stop_propagation();
} }
} }
@ -1133,7 +1148,6 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
state.update(cx, |state, cx| { state.update(cx, |state, cx| {
if state.is_dragging() { if state.is_dragging() {
state.scroll_handle().drag_ended(); state.scroll_handle().drag_ended();
state.notify_parent(cx);
} }
if !state.parent_hovered(&event.position) { if !state.parent_hovered(&event.position) {