Show embedded scrollbars only when necessary in scrollable

This commit is contained in:
Héctor Ramón Jiménez 2025-05-03 04:15:18 +02:00
parent 7a81e638a3
commit f78a87c409
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
3 changed files with 100 additions and 50 deletions

View file

@ -168,19 +168,17 @@ impl Tour {
Screen::End => self.end(), Screen::End => self.end(),
}; };
let content: Element<_> = column![screen, controls,] let content: Element<_> =
.max_width(540) column![screen, controls].max_width(540).spacing(20).into();
.spacing(20)
.padding(20)
.into();
let scrollable = scrollable(center_x(if self.debug { let scrollable = scrollable(center_x(if self.debug {
content.explain(Color::BLACK) content.explain(Color::BLACK)
} else { } else {
content content
})); }))
.spacing(10);
center_y(scrollable).into() center_y(scrollable).padding(10).into()
} }
fn can_continue(&self) -> bool { fn can_continue(&self) -> bool {

View file

@ -104,6 +104,7 @@ impl WebSocket {
) )
.id(MESSAGE_LOG.clone()) .id(MESSAGE_LOG.clone())
.height(Fill) .height(Fill)
.spacing(10)
.into() .into()
}; };

View file

@ -426,22 +426,7 @@ where
renderer: &Renderer, renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let (right_padding, bottom_padding) = match self.direction { let mut layout = |right_padding, bottom_padding| {
Direction::Vertical(Scrollbar {
width,
margin,
spacing: Some(spacing),
..
}) => (width + margin * 2.0 + spacing, 0.0),
Direction::Horizontal(Scrollbar {
width,
margin,
spacing: Some(spacing),
..
}) => (0.0, width + margin * 2.0 + spacing),
_ => (0.0, 0.0),
};
layout::padded( layout::padded(
limits, limits,
self.width, self.width,
@ -475,6 +460,70 @@ where
) )
}, },
) )
};
match self.direction {
Direction::Vertical(Scrollbar {
width,
margin,
spacing: Some(spacing),
..
})
| Direction::Horizontal(Scrollbar {
width,
margin,
spacing: Some(spacing),
..
}) => {
let is_vertical =
matches!(self.direction, Direction::Vertical(_));
let padding = width + margin * 2.0 + spacing;
let state = tree.state.downcast_mut::<State>();
let status_quo = layout(
if is_vertical && state.is_scrollbar_visible {
padding
} else {
0.0
},
if !is_vertical && state.is_scrollbar_visible {
padding
} else {
0.0
},
);
let is_scrollbar_visible = if is_vertical {
status_quo.children()[0].size().height
> status_quo.size().height
} else {
status_quo.children()[0].size().width
> status_quo.size().width
};
if state.is_scrollbar_visible == is_scrollbar_visible {
status_quo
} else {
log::trace!("Scrollbar status quo has changed");
state.is_scrollbar_visible = is_scrollbar_visible;
layout(
if is_vertical && state.is_scrollbar_visible {
padding
} else {
0.0
},
if !is_vertical && state.is_scrollbar_visible {
padding
} else {
0.0
},
)
}
}
_ => layout(0.0, 0.0),
}
} }
fn operate( fn operate(
@ -1354,6 +1403,7 @@ struct State {
keyboard_modifiers: keyboard::Modifiers, keyboard_modifiers: keyboard::Modifiers,
last_notified: Option<Viewport>, last_notified: Option<Viewport>,
last_scrolled: Option<Instant>, last_scrolled: Option<Instant>,
is_scrollbar_visible: bool,
} }
impl Default for State { impl Default for State {
@ -1367,6 +1417,7 @@ impl Default for State {
keyboard_modifiers: keyboard::Modifiers::default(), keyboard_modifiers: keyboard::Modifiers::default(),
last_notified: None, last_notified: None,
last_scrolled: None, last_scrolled: None,
is_scrollbar_visible: false,
} }
} }
} }
@ -1626,13 +1677,13 @@ impl Scrollbars {
) -> Self { ) -> Self {
let translation = state.translation(direction, bounds, content_bounds); let translation = state.translation(direction, bounds, content_bounds);
let show_scrollbar_x = direction.horizontal().filter(|scrollbar| { let show_scrollbar_x = direction
scrollbar.spacing.is_some() || content_bounds.width > bounds.width .horizontal()
}); .filter(|_scrollbar| content_bounds.width > bounds.width);
let show_scrollbar_y = direction.vertical().filter(|scrollbar| { let show_scrollbar_y = direction
scrollbar.spacing.is_some() || content_bounds.height > bounds.height .vertical()
}); .filter(|_scrollbar| content_bounds.height > bounds.height);
let y_scrollbar = if let Some(vertical) = show_scrollbar_y { let y_scrollbar = if let Some(vertical) = show_scrollbar_y {
let Scrollbar { let Scrollbar {