Scroll::preserve_max_scroll

This commit is contained in:
Jonathan Johnson 2024-10-06 09:44:37 -07:00
parent 77f1bd46f7
commit 432a84be04
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
2 changed files with 23 additions and 5 deletions

View file

@ -217,6 +217,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Choosing one or more folders/directories
- `DynamicGuard::unlocked` executes a closure while the guard is temporarily
unlocked.
- `Scroll::preserve_max_scroll` controls whether the scroll view automatically
scrolls when currently scrolled to the maximum and its child grows.
[139]: https://github.com/khonsulabs/cushy/issues/139

View file

@ -13,7 +13,7 @@ use crate::animation::{AnimationHandle, AnimationTarget, IntoAnimate, Spawn, Zer
use crate::context::{AsEventContext, EventContext, LayoutContext};
use crate::styles::components::{EasingIn, EasingOut, LineHeight};
use crate::styles::Dimension;
use crate::value::{Destination, Dynamic, Source};
use crate::value::{Destination, Dynamic, IntoValue, Source, Value};
use crate::widget::{EventHandling, MakeWidget, Widget, WidgetRef, HANDLED, IGNORED};
use crate::window::DeviceId;
use crate::ConstraintLimit;
@ -26,6 +26,7 @@ pub struct Scroll {
control_size: Size<Px>,
scroll: Dynamic<Point<Px>>,
enabled: Point<bool>,
preserve_max_scroll: Value<bool>,
max_scroll: Dynamic<Point<Px>>,
scrollbar_opacity: Dynamic<ZeroToOne>,
scrollbar_opacity_animation: OpacityAnimationState,
@ -64,6 +65,7 @@ impl Scroll {
bar_width: Px::default(),
line_height: Px::default(),
drag: DragInfo::default(),
preserve_max_scroll: Value::Constant(true),
}
}
@ -84,6 +86,18 @@ impl Scroll {
Self::construct(contents, Point::new(false, true))
}
/// Sets whether the scroll view will stay scrolled to the maximum when a
/// child is resized.
///
/// When enabled, this setting allows the scroll view to remain scrolled to
/// the bottom or to the right when its contents grow. The default value for
/// this setting is `true`.
#[must_use]
pub fn preserve_max_scroll(mut self, preserve: impl IntoValue<bool>) -> Self {
self.preserve_max_scroll = preserve.into_value();
self
}
fn constrained_scroll(scroll: Point<Px>, max_scroll: Point<Px>) -> Point<Px> {
scroll.max(max_scroll).min(Point::default())
}
@ -266,16 +280,18 @@ impl Widget for Scroll {
|| self.control_size.width != control_size.width
{
self.content_size.width = new_content_size.width;
let scroll_pct = scroll.x.into_float() / current_max_scroll.x.into_float();
scroll.x = max_scroll_x * scroll_pct;
if self.preserve_max_scroll.get() && scroll.x == current_max_scroll.x {
scroll.x = max_scroll_x;
}
}
if self.content_size.height != new_content_size.height
|| self.control_size.height != control_size.height
{
self.content_size.height = new_content_size.height;
let scroll_pct = scroll.y.into_float() / current_max_scroll.y.into_float();
scroll.y = max_scroll_y * scroll_pct;
if self.preserve_max_scroll.get() && scroll.y == current_max_scroll.y {
scroll.y = max_scroll_y;
}
}
// Set the current scroll, but prevent immediately triggering
// invalidate.