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.
use crate::{
AnyElement, App, AvailableSpace, Bounds, ContentMask, Element, ElementId, GlobalElementId,
Hitbox, InspectorElementId, InteractiveElement, Interactivity, IntoElement, IsZero, LayoutId,
ListSizingBehavior, Overflow, Pixels, Point, ScrollHandle, Size, StyleRefinement, Styled,
Window, point, size,
AnyElement, App, AvailableSpace, Bounds, ContentMask, Element, ElementId, Entity,
GlobalElementId, Hitbox, InspectorElementId, InteractiveElement, Interactivity, IntoElement,
IsZero, LayoutId, ListSizingBehavior, Overflow, Pixels, Point, ScrollHandle, Size,
StyleRefinement, Styled, Window, point, size,
};
use smallvec::SmallVec;
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
@ -71,7 +71,7 @@ pub struct UniformList {
/// Frame state used by the [UniformList].
pub struct UniformListFrameState {
items: SmallVec<[AnyElement; 32]>,
decorations: SmallVec<[AnyElement; 1]>,
decorations: SmallVec<[AnyElement; 2]>,
}
/// A handle for controlling the scroll position of a uniform list.
@ -529,6 +529,31 @@ pub trait UniformListDecoration {
) -> 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 {
/// Selects a specific list item for measurement.
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
// 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<S: ScrollbarVisibilitySetting, T: ScrollableHandle> UniformListDecoration
for ScrollbarStateWrapper<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 {
ScrollbarElement {
state: self.0.clone(),
}
.into_any()
}
}
// impl WithScrollbar for UniformList {
// type Output = 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)
// }
// }
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)]
pub enum ScrollAxes {
@ -568,6 +571,16 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
&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 {
self.thumb_state.is_dragging()
}
@ -1044,7 +1057,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
if thumb_bounds.contains(&event.position) {
let offset =
event.position.along(*axis) - thumb_bounds.origin.along(*axis);
state.set_dragging(*axis, offset, cx)
state.set_dragging(*axis, offset, cx);
} else {
let scroll_handle = state.scroll_handle();
let click_offset = scrollbar_layout.compute_click_offset(
@ -1052,12 +1065,13 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
scroll_handle.max_offset(),
ScrollbarMouseEvent::TrackClick,
);
scroll_handle.set_offset(
state.set_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 current_offset = scroll_handle.offset();
scroll_handle.set_offset(
current_offset + event.delta.pixel_delta(window.line_height()),
);
state.update(cx, |state, cx| state.show_scrollbars(cx));
state.update(cx, |state, cx| {
state.set_offset(
current_offset + event.delta.pixel_delta(window.line_height()),
cx,
);
state.show_scrollbars(cx);
cx.stop_propagation();
});
}
}
});
@ -1096,13 +1114,10 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
scroll_handle.max_offset(),
ScrollbarMouseEvent::ThumbDrag(drag_state),
);
scroll_handle.set_offset(
scroll_handle.offset().apply_along(axis, |_| drag_offset),
);
let new_offset =
scroll_handle.offset().apply_along(axis, |_| drag_offset);
// todo! Needed?
window.refresh();
state.update(cx, |state, cx| state.notify_parent(cx));
state.update(cx, |state, cx| state.set_offset(new_offset, cx));
cx.stop_propagation();
}
}
@ -1133,7 +1148,6 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
state.update(cx, |state, cx| {
if state.is_dragging() {
state.scroll_handle().drag_ended();
state.notify_parent(cx);
}
if !state.parent_hovered(&event.position) {