From 3da0c0aa604e539494811f0f3a6747173610d92e Mon Sep 17 00:00:00 2001 From: MrSubidubi Date: Sat, 16 Aug 2025 00:36:11 +0200 Subject: [PATCH] Some fixes, impl for uniformlist --- crates/outline_panel/src/outline_panel.rs | 16 +- crates/ui/src/components/scrollbar.rs | 182 ++++++++++++---------- 2 files changed, 104 insertions(+), 94 deletions(-) diff --git a/crates/outline_panel/src/outline_panel.rs b/crates/outline_panel/src/outline_panel.rs index 201f8f323c..b248b4d4a2 100644 --- a/crates/outline_panel/src/outline_panel.rs +++ b/crates/outline_panel/src/outline_panel.rs @@ -4553,7 +4553,6 @@ impl OutlinePanel { }; v_flex() - .id("outline-panel-empty") .flex_1() .justify_center() .size_full() @@ -4703,19 +4702,20 @@ impl OutlinePanel { ), ) }) + .custom_scrollbars( + Scrollbars::for_settings::() + .tracked_scroll_handle(self.scroll_handle.clone()) + .with_track_along(ScrollAxes::Horizontal) + .tracked_entity(cx.entity()), + window, + cx, + ) }; v_flex() .flex_shrink() .size_full() .child(list_contents.size_full().flex_shrink()) - .custom_scrollbars( - Scrollbars::for_settings::() - .tracked_scroll_handle(self.scroll_handle.clone()) - .with_track_along(ScrollAxes::Horizontal), - window, - cx, - ) } .children(self.context_menu.as_ref().map(|(menu, position, _)| { deferred( diff --git a/crates/ui/src/components/scrollbar.rs b/crates/ui/src/components/scrollbar.rs index 292e37f556..ec53a9c0a7 100644 --- a/crates/ui/src/components/scrollbar.rs +++ b/crates/ui/src/components/scrollbar.rs @@ -4,8 +4,8 @@ use gpui::{ Along, App, AppContext as _, Axis as ScrollbarAxis, BorderStyle, Bounds, ContentMask, Context, Corner, Corners, CursorStyle, Div, Edges, Element, ElementId, Entity, EntityId, GlobalElementId, Hitbox, HitboxBehavior, Hsla, InteractiveElement, IntoElement, IsZero, - LayoutId, ListState, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, - Pixels, Point, Position, Render, ScrollHandle, ScrollWheelEvent, Size, Stateful, + LayoutId, ListState, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Negate, + ParentElement, Pixels, Point, Position, Render, ScrollHandle, ScrollWheelEvent, Size, Stateful, StatefulInteractiveElement, Style, Styled, Task, UniformList, UniformListDecoration, UniformListScrollHandle, Window, prelude::FluentBuilder as _, px, quad, relative, size, }; @@ -217,24 +217,20 @@ where { let state = &scrollbar.read(cx).0; - if state.read(cx).disabled() { - div - } else { - div.when_some(state.read(cx).handle_to_track(), |this, handle| { - this.track_scroll(handle) - }) - .when_some( - state - .read(cx) - .space_to_reserve_for(ScrollbarAxis::Horizontal), - |this, space| this.pb(space), - ) - .when_some( - state.read(cx).space_to_reserve_for(ScrollbarAxis::Vertical), - |this, space| this.pr(space), - ) - .child(state.clone()) - } + div.when_some(state.read(cx).handle_to_track(), |this, handle| { + this.track_scroll(handle) + }) + .when_some( + state + .read(cx) + .space_to_reserve_for(ScrollbarAxis::Horizontal), + |this, space| this.pb(space), + ) + .when_some( + state.read(cx).space_to_reserve_for(ScrollbarAxis::Vertical), + |this, space| this.pr(space), + ) + .child(state.clone()) } impl UniformListDecoration @@ -244,13 +240,14 @@ impl UniformListDecoration &self, _visible_range: Range, _bounds: Bounds, - _scroll_offset: Point, + scroll_offset: Point, _item_height: Pixels, _item_count: usize, _window: &mut Window, _cx: &mut App, ) -> gpui::AnyElement { ScrollbarElement { + origin: scroll_offset.negate(), state: self.0.clone(), } .into_any() @@ -558,7 +555,11 @@ impl ScrollbarState { fn space_to_reserve_for(&self, axis: ScrollbarAxis) -> Option { (self.show_state.is_disabled().not() && self.visibility.along(axis).needs_scroll_track()) - .then(|| self.width.to_pixels() + 2 * SCROLLBAR_PADDING) + .then(|| self.space_to_reserve()) + } + + fn space_to_reserve(&self) -> Pixels { + self.width.to_pixels() + 2 * SCROLLBAR_PADDING } fn handle_to_track(&self) -> Option<&ScrollHandle> { @@ -692,11 +693,15 @@ impl ScrollbarState { impl Render for ScrollbarState { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - ScrollbarElement { state: cx.entity() } + ScrollbarElement { + state: cx.entity(), + origin: Default::default(), + } } } struct ScrollbarElement { + origin: Point, state: Entity>, } @@ -912,86 +917,91 @@ impl Element for ScrollbarEl window: &mut Window, cx: &mut App, ) -> Self::PrepaintState { - Some(ScrollbarPrepaintState { - parent_bounds: bounds, - thumbs: self - .state - .read(cx) - .thumb_ranges() - .map(|(axis, thumb_range, reserved_space)| { - let track_anchor = match axis { - ScrollbarAxis::Horizontal => Corner::BottomLeft, - ScrollbarAxis::Vertical => Corner::TopRight, - }; - let scroll_track_bounds = Bounds::from_corner_and_size( - track_anchor, - bounds - .corner(track_anchor) - .apply_along(axis.invert(), |corner| corner - SCROLLBAR_PADDING), - bounds - .size - .apply_along(axis.invert(), |_| self.state.read(cx).width.to_pixels()), - ); + self.state + .read(cx) + .disabled() + .not() + .then(|| ScrollbarPrepaintState { + parent_bounds: bounds, + thumbs: self + .state + .read(cx) + .thumb_ranges() + .map(|(axis, thumb_range, reserved_space)| { + let track_anchor = match axis { + ScrollbarAxis::Horizontal => Corner::BottomLeft, + ScrollbarAxis::Vertical => Corner::TopRight, + }; + let Bounds { origin, size } = Bounds::from_corner_and_size( + track_anchor, + bounds + .corner(track_anchor) + .apply_along(axis.invert(), |corner| corner - SCROLLBAR_PADDING), + bounds.size.apply_along(axis.invert(), |_| { + self.state.read(cx).width.to_pixels() + }), + ); + let scroll_track_bounds = Bounds::new(self.origin + origin, size); - let padded_bounds = scroll_track_bounds.extend(match axis { - ScrollbarAxis::Horizontal => Edges { - right: -SCROLLBAR_PADDING, - left: -SCROLLBAR_PADDING, - ..Default::default() - }, - ScrollbarAxis::Vertical => Edges { - top: -SCROLLBAR_PADDING, - bottom: -SCROLLBAR_PADDING, - ..Default::default() - }, - }); - - let thumb_offset = thumb_range.start * padded_bounds.size.along(axis); - let thumb_end = thumb_range.end * padded_bounds.size.along(axis); - - let thumb_bounds = Bounds::new( - padded_bounds - .origin - .apply_along(axis, |origin| origin + thumb_offset), - padded_bounds - .size - .apply_along(axis, |_| thumb_end - thumb_offset), - ); - - ScrollbarLayout { - thumb_bounds, - track_bounds: padded_bounds, - axis, - cursor_hitbox: window.insert_hitbox( - if reserved_space.needs_scroll_track() { - padded_bounds - } else { - thumb_bounds + let padded_bounds = scroll_track_bounds.extend(match axis { + ScrollbarAxis::Horizontal => Edges { + right: -SCROLLBAR_PADDING, + left: -SCROLLBAR_PADDING, + ..Default::default() }, - HitboxBehavior::BlockMouseExceptScroll, - ), - reserved_space, - } - }) - .collect(), - }) + ScrollbarAxis::Vertical => Edges { + top: -SCROLLBAR_PADDING, + bottom: -SCROLLBAR_PADDING, + ..Default::default() + }, + }); + + let thumb_offset = thumb_range.start * padded_bounds.size.along(axis); + let thumb_end = thumb_range.end * padded_bounds.size.along(axis); + + let thumb_bounds = Bounds::new( + padded_bounds + .origin + .apply_along(axis, |origin| origin + thumb_offset), + padded_bounds + .size + .apply_along(axis, |_| thumb_end - thumb_offset), + ); + + ScrollbarLayout { + thumb_bounds, + track_bounds: padded_bounds, + axis, + cursor_hitbox: window.insert_hitbox( + if reserved_space.needs_scroll_track() { + padded_bounds + } else { + thumb_bounds + }, + HitboxBehavior::BlockMouseExceptScroll, + ), + reserved_space, + } + }) + .collect(), + }) } fn paint( &mut self, _id: Option<&GlobalElementId>, _inspector_id: Option<&gpui::InspectorElementId>, - bounds: Bounds, + Bounds { origin, size }: Bounds, _request_layout: &mut Self::RequestLayoutState, prepaint_state: &mut Self::PrepaintState, window: &mut Window, cx: &mut App, ) { - // Practically, we'll never hit the case of this being none let Some(prepaint_state) = prepaint_state.take() else { return; }; + let bounds = Bounds::new(self.origin + origin, size); window.with_content_mask(Some(ContentMask { bounds }), |window| { let colors = cx.theme().colors();