use crate::prelude::*; pub struct Scroll { inner: WidgetHandle, axis: Axis, amt: f32, snap_end: bool, container_len: f32, content_len: f32, } impl Widget for Scroll { fn draw(&mut self, painter: &mut Painter) { let output_len = painter.output_size().axis(self.axis); let container_len = painter.region().axis(self.axis).len(); let content_len = painter .len_axis(&self.inner, self.axis) .apply_rest() .within_len(container_len) .to_abs(output_len); self.container_len = container_len.to_abs(output_len); self.content_len = content_len; if self.snap_end { self.amt = self.content_len - self.container_len; } self.update_amt(); let mut region = UiRegion::FULL.offset(Vec2::from_axis(self.axis, -self.amt, 0.0)); region.axis_mut(self.axis).end = region.axis(self.axis).start.offset(self.content_len); painter.widget_within(&self.inner, region); } fn desired_width(&mut self, ctx: &mut SizeCtx) -> Len { ctx.width(&self.inner) } fn desired_height(&mut self, ctx: &mut SizeCtx) -> Len { ctx.height(&self.inner) } } impl Scroll { pub fn new(inner: WidgetHandle, axis: Axis) -> Self { Self { inner, axis, amt: 0.0, snap_end: true, container_len: 0.0, content_len: 0.0, } } pub fn update_amt(&mut self) { self.amt = self.amt.max(0.0); let len = (self.content_len - self.container_len).max(0.0); self.amt = self.amt.min(len); self.snap_end = self.amt == len; } pub fn scroll(&mut self, amt: f32) { self.amt -= amt; self.update_amt(); } }