Disambiguate offset from translation in scrollable

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

View file

@ -198,15 +198,6 @@ pub enum Alignment {
End, End,
} }
impl Alignment {
fn aligned(self, offset: f32, viewport: f32, content: f32) -> f32 {
match self {
Alignment::Start => offset,
Alignment::End => ((content - viewport).max(0.0) - offset).max(0.0),
}
}
}
impl<'a, Message, Renderer> Widget<Message, Renderer> impl<'a, Message, Renderer> Widget<Message, Renderer>
for Scrollable<'a, Message, Renderer> for Scrollable<'a, Message, Renderer>
where where
@ -385,13 +376,12 @@ where
let bounds = layout.bounds(); let bounds = layout.bounds();
let content_layout = layout.children().next().unwrap(); let content_layout = layout.children().next().unwrap();
let content_bounds = content_layout.bounds(); let content_bounds = content_layout.bounds();
let offset = tree.state.downcast_ref::<State>().offset( let translation = tree
self.direction, .state
bounds, .downcast_ref::<State>()
content_bounds, .translation(self.direction, bounds, content_bounds);
);
overlay.translate(Vector::new(-offset.x, -offset.y)) overlay.translate(Vector::new(-translation.x, -translation.y))
}) })
} }
} }
@ -522,7 +512,7 @@ pub fn update<Message>(
{ {
mouse::Cursor::Available( mouse::Cursor::Available(
cursor_position cursor_position
+ state.offset(direction, bounds, content_bounds), + state.translation(direction, bounds, content_bounds),
) )
} }
_ => mouse::Cursor::Unavailable, _ => mouse::Cursor::Unavailable,
@ -798,13 +788,13 @@ pub fn mouse_interaction(
{ {
mouse::Interaction::Idle mouse::Interaction::Idle
} else { } else {
let offset = state.offset(direction, bounds, content_bounds); let translation = state.translation(direction, bounds, content_bounds);
let cursor = match cursor_over_scrollable { let cursor = match cursor_over_scrollable {
Some(cursor_position) Some(cursor_position)
if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) =>
{ {
mouse::Cursor::Available(cursor_position + offset) mouse::Cursor::Available(cursor_position + translation)
} }
_ => mouse::Cursor::Unavailable, _ => mouse::Cursor::Unavailable,
}; };
@ -813,8 +803,8 @@ pub fn mouse_interaction(
content_layout, content_layout,
cursor, cursor,
&Rectangle { &Rectangle {
y: bounds.y + offset.y, y: bounds.y + translation.y,
x: bounds.x + offset.x, x: bounds.x + translation.x,
..bounds ..bounds
}, },
) )
@ -845,13 +835,13 @@ pub fn draw<Renderer>(
let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) = let (mouse_over_y_scrollbar, mouse_over_x_scrollbar) =
scrollbars.is_mouse_over(cursor); scrollbars.is_mouse_over(cursor);
let offset = state.offset(direction, bounds, content_bounds); let translation = state.translation(direction, bounds, content_bounds);
let cursor = match cursor_over_scrollable { let cursor = match cursor_over_scrollable {
Some(cursor_position) Some(cursor_position)
if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) =>
{ {
mouse::Cursor::Available(cursor_position + offset) mouse::Cursor::Available(cursor_position + translation)
} }
_ => mouse::Cursor::Unavailable, _ => mouse::Cursor::Unavailable,
}; };
@ -860,15 +850,15 @@ pub fn draw<Renderer>(
if scrollbars.active() { if scrollbars.active() {
renderer.with_layer(bounds, |renderer| { renderer.with_layer(bounds, |renderer| {
renderer.with_translation( renderer.with_translation(
Vector::new(-offset.x, -offset.y), Vector::new(-translation.x, -translation.y),
|renderer| { |renderer| {
draw_content( draw_content(
renderer, renderer,
content_layout, content_layout,
cursor, cursor,
&Rectangle { &Rectangle {
y: bounds.y + offset.y, y: bounds.y + translation.y,
x: bounds.x + offset.x, x: bounds.x + translation.x,
..bounds ..bounds
}, },
); );
@ -959,8 +949,8 @@ pub fn draw<Renderer>(
content_layout, content_layout,
cursor, cursor,
&Rectangle { &Rectangle {
x: bounds.x + offset.x, x: bounds.x + translation.x,
y: bounds.y + offset.y, y: bounds.y + translation.y,
..bounds ..bounds
}, },
); );
@ -1067,6 +1057,20 @@ impl Offset {
} }
} }
} }
fn absolute_from_start(
self,
viewport: f32,
content: f32,
alignment: Alignment,
) -> f32 {
let offset = self.absolute(viewport, content);
match alignment {
Alignment::Start => offset,
Alignment::End => ((content - viewport).max(0.0) - offset).max(0.0),
}
}
} }
/// The current [`Viewport`] of the [`Scrollable`]. /// The current [`Viewport`] of the [`Scrollable`].
@ -1205,9 +1209,9 @@ impl State {
); );
} }
/// Returns the scrolling offset of the [`State`], given a [`Direction`], /// Returns the scrolling translation of the [`State`], given a [`Direction`],
/// the bounds of the [`Scrollable`] and its contents. /// the bounds of the [`Scrollable`] and its contents.
pub fn offset( fn translation(
&self, &self,
direction: Direction, direction: Direction,
bounds: Rectangle, bounds: Rectangle,
@ -1215,20 +1219,19 @@ impl State {
) -> Vector { ) -> Vector {
Vector::new( Vector::new(
if let Some(horizontal) = direction.horizontal() { if let Some(horizontal) = direction.horizontal() {
horizontal.alignment.aligned( self.offset_x.absolute_from_start(
self.offset_x.absolute(bounds.width, content_bounds.width),
bounds.width, bounds.width,
content_bounds.width, content_bounds.width,
horizontal.alignment,
) )
} else { } else {
0.0 0.0
}, },
if let Some(vertical) = direction.vertical() { if let Some(vertical) = direction.vertical() {
vertical.alignment.aligned( self.offset_y.absolute_from_start(
self.offset_y
.absolute(bounds.height, content_bounds.height),
bounds.height, bounds.height,
content_bounds.height, content_bounds.height,
vertical.alignment,
) )
} else { } else {
0.0 0.0
@ -1258,7 +1261,7 @@ impl Scrollbars {
bounds: Rectangle, bounds: Rectangle,
content_bounds: Rectangle, content_bounds: Rectangle,
) -> Self { ) -> Self {
let offset = state.offset(direction, bounds, content_bounds); let translation = state.translation(direction, bounds, content_bounds);
let show_scrollbar_x = direction let show_scrollbar_x = direction
.horizontal() .horizontal()
@ -1305,7 +1308,7 @@ impl Scrollbars {
let ratio = bounds.height / content_bounds.height; let ratio = bounds.height / content_bounds.height;
// min height for easier grabbing with super tall content // min height for easier grabbing with super tall content
let scroller_height = (bounds.height * ratio).max(2.0); let scroller_height = (bounds.height * ratio).max(2.0);
let scroller_offset = offset.y * ratio; let scroller_offset = translation.y * ratio;
let scroller_bounds = Rectangle { let scroller_bounds = Rectangle {
x: bounds.x + bounds.width x: bounds.x + bounds.width
@ -1366,7 +1369,7 @@ impl Scrollbars {
let ratio = bounds.width / content_bounds.width; let ratio = bounds.width / content_bounds.width;
// min width for easier grabbing with extra wide content // min width for easier grabbing with extra wide content
let scroller_length = (bounds.width * ratio).max(2.0); let scroller_length = (bounds.width * ratio).max(2.0);
let scroller_offset = offset.x * ratio; let scroller_offset = translation.x * ratio;
let scroller_bounds = Rectangle { let scroller_bounds = Rectangle {
x: (scrollbar_bounds.x + scroller_offset - scrollbar_y_width) x: (scrollbar_bounds.x + scroller_offset - scrollbar_y_width)