Reduce clones

This commit is contained in:
MrSubidubi 2025-08-13 14:56:49 +02:00
parent 3b611313e1
commit afcfd0979a

View file

@ -411,6 +411,7 @@ impl VisibilityState {
matches!(self, VisibilityState::Visible) matches!(self, VisibilityState::Visible)
} }
#[inline]
fn is_disabled(&self) -> bool { fn is_disabled(&self) -> bool {
matches!(self, VisibilityState::Disabled) matches!(self, VisibilityState::Disabled)
} }
@ -427,6 +428,7 @@ struct ScrollbarState<S: ScrollbarVisibilitySetting, T: ScrollableHandle = Scrol
show_setting: ShowScrollbar, show_setting: ShowScrollbar,
visibility: Point<ReservedSpace>, visibility: Point<ReservedSpace>,
show_state: VisibilityState, show_state: VisibilityState,
last_prepaint_state: Option<ScrollbarPrepaintState>,
_auto_hide_task: Option<Task<()>>, _auto_hide_task: Option<Task<()>>,
} }
@ -449,6 +451,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
tracked_setting: PhantomData, tracked_setting: PhantomData,
show_setting: ShowScrollbar::Always, show_setting: ShowScrollbar::Always,
show_state: VisibilityState::Visible, show_state: VisibilityState::Visible,
last_prepaint_state: None,
_auto_hide_task: None, _auto_hide_task: None,
}; };
state.schedule_auto_hide(window, cx); state.schedule_auto_hide(window, cx);
@ -528,13 +531,13 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
self.scroll_handle().drag_started(); self.scroll_handle().drag_started();
} }
fn set_hovered_thumb( fn update_hovered_thumb(&mut self, position: &Point<Pixels>, cx: &mut Context<Self>) {
&mut self,
hovered_thumb: Option<&ScrollbarLayout>,
cx: &mut Context<Self>,
) {
self.set_thumb_state( self.set_thumb_state(
if let Some(&ScrollbarLayout { axis, .. }) = hovered_thumb { if let Some(&ScrollbarLayout { axis, .. }) = self
.last_prepaint_state
.as_ref()
.and_then(|state| state.thumb_for_position(position))
{
ThumbState::Hover(axis) ThumbState::Hover(axis)
} else { } else {
ThumbState::Inactive ThumbState::Inactive
@ -550,6 +553,30 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
} }
} }
fn parent_hovered(&self, position: &Point<Pixels>) -> bool {
self.last_prepaint_state
.as_ref()
.is_some_and(|state| state.parent_bounds.contains(position))
}
fn thumb_for_position(&self, position: &Point<Pixels>) -> Option<&ScrollbarLayout> {
self.last_prepaint_state
.as_ref()
.and_then(|state| state.thumb_for_position(position))
}
fn hit_for_position(&self, position: &Point<Pixels>) -> Option<&ScrollbarLayout> {
self.last_prepaint_state
.as_ref()
.and_then(|state| state.hit_for_position(position))
}
fn thumb_for_axis(&self, axis: ScrollbarAxis) -> Option<&ScrollbarLayout> {
self.last_prepaint_state
.as_ref()
.and_then(|state| state.thumbs.iter().find(|thumb| thumb.axis == axis))
}
fn thumb_ranges( fn thumb_ranges(
&self, &self,
) -> impl Iterator<Item = (ScrollbarAxis, Range<f32>, ReservedSpace)> + '_ { ) -> impl Iterator<Item = (ScrollbarAxis, Range<f32>, ReservedSpace)> + '_ {
@ -592,6 +619,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> ScrollbarState<S, T> {
self.show_state.is_visible() self.show_state.is_visible()
} }
#[inline]
fn disabled(&self) -> bool { fn disabled(&self) -> bool {
self.show_state.is_disabled() self.show_state.is_disabled()
} }
@ -825,7 +853,6 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
window: &mut Window, window: &mut Window,
cx: &mut App, cx: &mut App,
) -> Self::PrepaintState { ) -> Self::PrepaintState {
window.with_content_mask(Some(ContentMask { bounds }), |window| {
Some(ScrollbarPrepaintState { Some(ScrollbarPrepaintState {
parent_bounds: bounds, parent_bounds: bounds,
thumbs: self thumbs: self
@ -842,9 +869,9 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
bounds bounds
.corner(track_anchor) .corner(track_anchor)
.apply_along(axis.invert(), |corner| corner - SCROLLBAR_PADDING), .apply_along(axis.invert(), |corner| corner - SCROLLBAR_PADDING),
bounds.size.apply_along(axis.invert(), |_| { bounds
self.state.read(cx).width.to_pixels() .size
}), .apply_along(axis.invert(), |_| self.state.read(cx).width.to_pixels()),
); );
let padded_bounds = scroll_track_bounds.extend(match axis { let padded_bounds = scroll_track_bounds.extend(match axis {
@ -889,7 +916,6 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
}) })
.collect(), .collect(),
}) })
})
} }
fn paint( fn paint(
@ -948,14 +974,18 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
} }
} }
self.state.update(cx, |state, _| {
state.last_prepaint_state = Some(prepaint_state)
});
window.on_mouse_event({ window.on_mouse_event({
let state = self.state.clone(); let state = self.state.clone();
// todo! Can this be removed?
let prepaint_state = prepaint_state.clone();
move |event: &MouseDownEvent, phase, _, cx| { move |event: &MouseDownEvent, phase, _, cx| {
state.update(cx, |state, cx| {
let Some(scrollbar_layout) = (phase.capture() let Some(scrollbar_layout) = (phase.capture()
&& event.button == MouseButton::Left) && event.button == MouseButton::Left)
.then(|| prepaint_state.hit_for_position(&event.position)) .then(|| state.hit_for_position(&event.position))
.flatten() .flatten()
else { else {
return; return;
@ -966,11 +996,11 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
} = scrollbar_layout; } = scrollbar_layout;
if thumb_bounds.contains(&event.position) { if thumb_bounds.contains(&event.position) {
let offset = event.position.along(*axis) - thumb_bounds.origin.along(*axis); let offset =
// todo! event.position.along(*axis) - thumb_bounds.origin.along(*axis);
state.update(cx, |state, cx| state.set_dragging(*axis, offset, cx)); state.set_dragging(*axis, offset, cx)
} else { } else {
let scroll_handle = state.read(cx).scroll_handle(); let scroll_handle = state.scroll_handle();
let click_offset = scrollbar_layout.compute_click_offset( let click_offset = scrollbar_layout.compute_click_offset(
event.position, event.position,
scroll_handle.max_offset(), scroll_handle.max_offset(),
@ -982,15 +1012,16 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
cx.stop_propagation(); cx.stop_propagation();
} }
});
} }
}); });
window.on_mouse_event({ window.on_mouse_event({
let state = self.state.clone(); let state = self.state.clone();
// todo! can this be removed?
let prepaint_state = prepaint_state.clone();
move |event: &ScrollWheelEvent, phase, window, cx| { move |event: &ScrollWheelEvent, phase, window, cx| {
if phase.capture() && prepaint_state.hit_for_position(&event.position).is_some() if phase.capture()
&& state.read(cx).thumb_for_position(&event.position).is_some()
{ {
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();
@ -1004,8 +1035,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
window.on_mouse_event({ window.on_mouse_event({
let state = self.state.clone(); let state = self.state.clone();
// todo! can this be removed?
let prepaint_state = prepaint_state.clone();
move |event: &MouseMoveEvent, phase, window, cx| { move |event: &MouseMoveEvent, phase, window, cx| {
if !phase.capture() { if !phase.capture() {
return; return;
@ -1013,11 +1043,7 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
match state.read(cx).thumb_state { match state.read(cx).thumb_state {
ThumbState::Dragging(axis, drag_state) if event.dragging() => { ThumbState::Dragging(axis, drag_state) if event.dragging() => {
if let Some(scrollbar_layout) = prepaint_state if let Some(scrollbar_layout) = state.read(cx).thumb_for_axis(axis) {
.thumbs
.iter()
.find(|thumb| thumb.axis == axis)
{
let scroll_handle = state.read(cx).scroll_handle(); let scroll_handle = state.read(cx).scroll_handle();
let drag_offset = scrollbar_layout.compute_click_offset( let drag_offset = scrollbar_layout.compute_click_offset(
event.position, event.position,
@ -1035,14 +1061,12 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
} }
} }
_ => state.update(cx, |state, cx| { _ => state.update(cx, |state, cx| {
if prepaint_state.parent_bounds.contains(&event.position) { if state.parent_hovered(&event.position) {
// todo! this should only be fired on first re-enter, if at all // todo! this should only be fired on first re-enter, if at all
state.show_scrollbars(cx); state.show_scrollbars(cx);
if event.pressed_button.is_none() { if event.pressed_button.is_none() {
state.set_hovered_thumb( state.update_hovered_thumb(&event.position, cx);
prepaint_state.thumb_for_position(&event.position),
cx,
);
cx.stop_propagation(); cx.stop_propagation();
} }
} else { } else {
@ -1066,15 +1090,12 @@ impl<S: ScrollbarVisibilitySetting, T: ScrollableHandle> Element for ScrollbarEl
state.notify_parent(cx); state.notify_parent(cx);
} }
if !prepaint_state.parent_bounds.contains(&event.position) { if !state.parent_hovered(&event.position) {
state.schedule_auto_hide(window, cx); state.schedule_auto_hide(window, cx);
return; return;
} }
state.set_hovered_thumb( state.update_hovered_thumb(&event.position, cx);
prepaint_state.thumb_for_position(&event.position),
cx,
);
}); });
} }
}); });