Reduce clones
This commit is contained in:
parent
3b611313e1
commit
afcfd0979a
1 changed files with 137 additions and 116 deletions
|
@ -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);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue