Increase type-safety of alignment in scrollable

This commit is contained in:
Héctor Ramón Jiménez 2023-07-12 09:49:14 +02:00
parent 44460f7b8b
commit 2b2f9c07d8
No known key found for this signature in database
GPG key ID: 140CC052C94F138E

View file

@ -295,7 +295,7 @@ where
cursor,
clipboard,
shell,
&self.direction,
self.direction,
&self.on_scroll,
|event, layout, cursor, clipboard, shell| {
self.content.as_widget_mut().on_event(
@ -327,7 +327,7 @@ where
theme,
layout,
cursor,
&self.direction,
self.direction,
&self.style,
|renderer, layout, cursor, viewport| {
self.content.as_widget().draw(
@ -355,7 +355,7 @@ where
tree.state.downcast_ref::<State>(),
layout,
cursor,
&self.direction,
self.direction,
|layout, cursor, viewport| {
self.content.as_widget().mouse_interaction(
&tree.children[0],
@ -386,7 +386,7 @@ where
let content_layout = layout.children().next().unwrap();
let content_bounds = content_layout.bounds();
let offset = tree.state.downcast_ref::<State>().offset(
&self.direction,
self.direction,
bounds,
content_bounds,
);
@ -494,7 +494,7 @@ pub fn update<Message>(
cursor: mouse::Cursor,
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
direction: &Direction,
direction: Direction,
on_scroll: &Option<Box<dyn Fn(Viewport) -> Message + '_>>,
update_content: impl FnOnce(
Event,
@ -512,15 +512,6 @@ pub fn update<Message>(
let scrollbars = Scrollbars::new(state, direction, bounds, content_bounds);
let horizontal_alignment = direction
.horizontal()
.map(|p| p.alignment)
.unwrap_or_default();
let vertical_alignment = direction
.vertical()
.map(|p| p.alignment)
.unwrap_or_default();
let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) =
scrollbars.is_mouse_over(cursor);
@ -571,11 +562,7 @@ pub fn update<Message>(
mouse::ScrollDelta::Pixels { x, y } => Vector::new(x, y),
};
state.scroll(
aligned_delta(delta, vertical_alignment, horizontal_alignment),
bounds,
content_bounds,
);
state.scroll(delta, direction, bounds, content_bounds);
notify_on_scroll(state, on_scroll, bounds, content_bounds, shell);
@ -606,15 +593,7 @@ pub fn update<Message>(
cursor_position.y - scroll_box_touched_at.y,
);
state.scroll(
aligned_delta(
delta,
vertical_alignment,
horizontal_alignment,
),
bounds,
content_bounds,
);
state.scroll(delta, direction, bounds, content_bounds);
state.scroll_area_touched_at = Some(cursor_position);
@ -658,7 +637,6 @@ pub fn update<Message>(
scrollbar.scroll_percentage_y(
scroller_grabbed_at,
cursor_position,
vertical_alignment,
),
bounds,
content_bounds,
@ -692,7 +670,6 @@ pub fn update<Message>(
scrollbar.scroll_percentage_y(
scroller_grabbed_at,
cursor_position,
vertical_alignment,
),
bounds,
content_bounds,
@ -735,7 +712,6 @@ pub fn update<Message>(
scrollbar.scroll_percentage_x(
scroller_grabbed_at,
cursor_position,
horizontal_alignment,
),
bounds,
content_bounds,
@ -769,7 +745,6 @@ pub fn update<Message>(
scrollbar.scroll_percentage_x(
scroller_grabbed_at,
cursor_position,
horizontal_alignment,
),
bounds,
content_bounds,
@ -800,7 +775,7 @@ pub fn mouse_interaction(
state: &State,
layout: Layout<'_>,
cursor: mouse::Cursor,
direction: &Direction,
direction: Direction,
content_interaction: impl FnOnce(
Layout<'_>,
mouse::Cursor,
@ -853,7 +828,7 @@ pub fn draw<Renderer>(
theme: &Renderer::Theme,
layout: Layout<'_>,
cursor: mouse::Cursor,
direction: &Direction,
direction: Direction,
style: &<Renderer::Theme as StyleSheet>::Style,
draw_content: impl FnOnce(&mut Renderer, Layout<'_>, mouse::Cursor, &Rectangle),
) where
@ -1138,9 +1113,30 @@ impl State {
pub fn scroll(
&mut self,
delta: Vector<f32>,
direction: Direction,
bounds: Rectangle,
content_bounds: Rectangle,
) {
let horizontal_alignment = direction
.horizontal()
.map(|p| p.alignment)
.unwrap_or_default();
let vertical_alignment = direction
.vertical()
.map(|p| p.alignment)
.unwrap_or_default();
let align = |alignment: Alignment, delta: f32| match alignment {
Alignment::Start => delta,
Alignment::End => -delta,
};
let delta = Vector::new(
align(horizontal_alignment, delta.x),
align(vertical_alignment, delta.y),
);
if bounds.height < content_bounds.height {
self.offset_y = Offset::Absolute(
(self.offset_y.absolute(bounds.height, content_bounds.height)
@ -1213,7 +1209,7 @@ impl State {
/// the bounds of the [`Scrollable`] and its contents.
pub fn offset(
&self,
direction: &Direction,
direction: Direction,
bounds: Rectangle,
content_bounds: Rectangle,
) -> Vector {
@ -1258,7 +1254,7 @@ impl Scrollbars {
/// Create y and/or x scrollbar(s) if content is overflowing the [`Scrollable`] bounds.
fn new(
state: &State,
direction: &Direction,
direction: Direction,
bounds: Rectangle,
content_bounds: Rectangle,
) -> Self {
@ -1327,6 +1323,7 @@ impl Scrollbars {
scroller: internals::Scroller {
bounds: scroller_bounds,
},
alignment: vertical.alignment,
})
} else {
None
@ -1387,6 +1384,7 @@ impl Scrollbars {
scroller: internals::Scroller {
bounds: scroller_bounds,
},
alignment: horizontal.alignment,
})
} else {
None
@ -1450,39 +1448,17 @@ impl Scrollbars {
}
}
fn aligned_delta(
delta: Vector,
vertical_alignment: Alignment,
horizontal_alignment: Alignment,
) -> Vector {
let align = |alignment: Alignment, delta: f32| match alignment {
Alignment::Start => delta,
Alignment::End => -delta,
};
Vector::new(
align(horizontal_alignment, delta.x),
align(vertical_alignment, delta.y),
)
}
pub(super) mod internals {
use crate::core::{Point, Rectangle};
use super::Alignment;
/// The scrollbar of a [`Scrollable`].
#[derive(Debug, Copy, Clone)]
pub struct Scrollbar {
/// The total bounds of the [`Scrollbar`], including the scrollbar, the scroller,
/// and the scrollbar margin.
pub total_bounds: Rectangle,
/// The bounds of just the [`Scrollbar`].
pub bounds: Rectangle,
/// The state of this scrollbar's [`Scroller`].
pub scroller: Scroller,
pub alignment: Alignment,
}
impl Scrollbar {
@ -1496,7 +1472,6 @@ pub(super) mod internals {
&self,
grabbed_at: f32,
cursor_position: Point,
alignment: Alignment,
) -> f32 {
let pct = if cursor_position.x < 0.0 && cursor_position.y < 0.0 {
// cursor position is unavailable! Set to either end or beginning of scrollbar depending
@ -1509,7 +1484,7 @@ pub(super) mod internals {
/ (self.bounds.height - self.scroller.bounds.height)
};
match alignment {
match self.alignment {
Alignment::Start => pct,
Alignment::End => 1.0 - pct,
}
@ -1520,7 +1495,6 @@ pub(super) mod internals {
&self,
grabbed_at: f32,
cursor_position: Point,
alignment: Alignment,
) -> f32 {
let pct = if cursor_position.x < 0.0 && cursor_position.y < 0.0 {
(self.scroller.bounds.x / self.total_bounds.width).round()
@ -1531,7 +1505,7 @@ pub(super) mod internals {
/ (self.bounds.width - self.scroller.bounds.width)
};
match alignment {
match self.alignment {
Alignment::Start => pct,
Alignment::End => 1.0 - pct,
}