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