Fixed Align::FILL in scroll.

This commit is contained in:
Samuel Guerra 2023-09-13 23:47:56 -03:00
parent 1ff0769f9b
commit bcc1dee304
4 changed files with 59 additions and 31 deletions

View File

@ -32,8 +32,11 @@
# Scroll
* `scroll_to` does not work correctly when requested by text `line_up`
* `scroll_to` does not work correctly when requested by text `line_up`.
- Never works correctly when target is above.
* Implement touch scroll inertia.
* Fill forces min-size.
- Needs to work the same as `Container!`.
# Touch Events

View File

@ -141,11 +141,16 @@ fn scroll_node(
nodes::scrollbar_joiner_presenter(),
];
let scroll_info = ScrollInfo::default();
let mut viewport = PxSize::zero();
let mut joiner = PxSize::zero();
let spatial_id = SpatialFrameId::new_unique();
match_node_list(children, move |children, op| match op {
UiNodeOp::Info { info } => {
info.set_meta(&SCROLL_INFO_ID, scroll_info.clone());
}
UiNodeOp::Measure { wm, desired_size } => {
let constraints = LAYOUT.constraints();
*desired_size = if constraints.is_fill_max().all() {
@ -177,24 +182,11 @@ fn scroll_node(
// joiner
let _ = LAYOUT.with_constraints(PxConstraints2d::new_fill_size(joiner), || children.with_node(3, |n| n.layout(wl)));
scroll_info.set_joiner_size(joiner);
// viewport
let mut vp = LAYOUT.with_constraints(c.with_less_size(joiner), || children.with_node(0, |n| n.layout(wl)));
// arrange
let fs = vp + joiner;
let content_size = SCROLL_CONTENT_SIZE_VAR.get();
if content_size.height > fs.height {
SCROLL_VERTICAL_CONTENT_OVERFLOWS_VAR.set(true).unwrap();
SCROLL_HORIZONTAL_CONTENT_OVERFLOWS_VAR.set(content_size.width > vp.width).unwrap();
} else if content_size.width > fs.width {
SCROLL_HORIZONTAL_CONTENT_OVERFLOWS_VAR.set(true).unwrap();
SCROLL_VERTICAL_CONTENT_OVERFLOWS_VAR.set(content_size.height > vp.height).unwrap();
} else {
SCROLL_VERTICAL_CONTENT_OVERFLOWS_VAR.set(false).unwrap();
SCROLL_HORIZONTAL_CONTENT_OVERFLOWS_VAR.set(false).unwrap();
}
// collapse scrollbars if they take more the 1/3 of the total area.
if vp.width < joiner.width * 3.0.fct() {
vp.width += joiner.width;

View File

@ -27,7 +27,12 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
let mut content_scale = 1.fct();
let mut auto_hide_extra = PxSideOffsets::zero();
let mut last_render_offset = PxVector::zero();
let scroll_info = ScrollInfo::default();
let mut scroll_info = None;
let mut scroll_info = move || {
scroll_info
.get_or_insert_with(|| WIDGET.info().meta().get_clone(&SCROLL_INFO_ID).unwrap())
.clone()
};
match_node(child, move |child, op| match op {
UiNodeOp::Init => {
@ -38,9 +43,7 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
.sub_var_layout(&SCROLL_SCALE_VAR)
.sub_var_layout(&child_align);
}
UiNodeOp::Info { info } => {
info.set_meta(&SCROLL_INFO_ID, scroll_info.clone());
}
UiNodeOp::Measure { wm, desired_size } => {
let constraints = LAYOUT.constraints();
if constraints.is_fill_max().all() {
@ -60,13 +63,12 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
let mut content_size = LAYOUT.with_constraints(
{
let mut c = child_align.child_constraints(constraints);
c = c.with_min_size(viewport_unit);
let mut c = child_align.child_constraints(constraints.with_new_min_size(viewport_unit));
if mode.contains(ScrollMode::VERTICAL) {
c = c.with_unbounded_y().with_new_min_y(Px(0));
c = c.with_unbounded_y();
}
if mode.contains(ScrollMode::HORIZONTAL) {
c = c.with_unbounded_x().with_new_min_x(Px(0));
c = c.with_unbounded_x();
}
c
},
@ -97,16 +99,17 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
&& vp_unit.width > Px(0) // and has fill-size
&& vp_unit.height > Px(0)
&& constraints.max_size() == Some(vp_unit); // that is not just min size.
let joiner_size = scroll_info().joiner_size();
let mut content_size = LAYOUT.with_constraints(
{
let mut c = child_align.child_constraints(constraints);
c = c.with_min_size(vp_unit);
let mut c = child_align.child_constraints(constraints.with_new_min_size(vp_unit + joiner_size));
if mode.contains(ScrollMode::VERTICAL) {
c = c.with_unbounded_y().with_new_min_y(Px(0));
c = c.with_unbounded_y();
}
if mode.contains(ScrollMode::HORIZONTAL) {
c = c.with_unbounded_x().with_new_min_x(Px(0));
c = c.with_unbounded_x();
}
c
},
@ -146,7 +149,7 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
auto_hide_extra.bottom = auto_hide_extra.bottom.max(Px(0));
auto_hide_extra.left = auto_hide_extra.left.max(Px(0));
scroll_info.set_viewport_size(vp_size);
scroll_info().set_viewport_size(vp_size);
let align_offset = child_align.child_offset(content_size, viewport_size, LAYOUT.direction());
@ -199,10 +202,27 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
SCROLL_HORIZONTAL_RATIO_VAR.set(h_ratio.fct()).unwrap();
SCROLL_CONTENT_SIZE_VAR.set(content_size).unwrap();
let full_size = viewport_size + joiner_size;
if content_size.height > full_size.height {
SCROLL_VERTICAL_CONTENT_OVERFLOWS_VAR.set(true).unwrap();
SCROLL_HORIZONTAL_CONTENT_OVERFLOWS_VAR
.set(content_size.width > viewport_size.width)
.unwrap();
} else if content_size.width > full_size.width {
SCROLL_HORIZONTAL_CONTENT_OVERFLOWS_VAR.set(true).unwrap();
SCROLL_VERTICAL_CONTENT_OVERFLOWS_VAR
.set(content_size.height > viewport_size.height)
.unwrap();
} else {
SCROLL_VERTICAL_CONTENT_OVERFLOWS_VAR.set(false).unwrap();
SCROLL_HORIZONTAL_CONTENT_OVERFLOWS_VAR.set(false).unwrap();
}
*final_size = viewport_size;
}
UiNodeOp::Render { frame } => {
scroll_info.set_viewport_transform(*frame.transform());
scroll_info().set_viewport_transform(*frame.transform());
last_render_offset = content_offset;
let mut culling_rect = PxBox::from_size(viewport_size);
@ -224,7 +244,7 @@ pub fn viewport(child: impl UiNode, mode: impl IntoVar<ScrollMode>, child_align:
});
}
UiNodeOp::RenderUpdate { update } => {
scroll_info.set_viewport_transform(*update.transform());
scroll_info().set_viewport_transform(*update.transform());
let transform = if content_scale != 1.fct() {
PxTransform::scale(content_scale.0, content_scale.0).then_translate(content_offset.cast())

View File

@ -865,6 +865,7 @@ impl WidgetInfoExt for WidgetInfo {
struct ScrollData {
viewport_transform: PxTransform,
viewport_size: PxSize,
joiner_size: PxSize,
}
/// Shared reference to the viewport bounds of a scroll.
@ -889,6 +890,14 @@ impl ScrollInfo {
self.0.lock().viewport_transform
}
/// Gets the layout size of both scroll-bars.
///
/// Joiner here is the corner joiner visual, it is sized by the width of the vertical bar and
/// height of the horizontal bar.
pub fn joiner_size(&self) -> PxSize {
self.0.lock().joiner_size
}
pub(super) fn set_viewport_size(&self, size: PxSize) {
self.0.lock().viewport_size = size;
}
@ -896,6 +905,10 @@ impl ScrollInfo {
pub(super) fn set_viewport_transform(&self, transform: PxTransform) {
self.0.lock().viewport_transform = transform;
}
pub(super) fn set_joiner_size(&self, size: PxSize) {
self.0.lock().joiner_size = size;
}
}
pub(super) static SCROLL_INFO_ID: StaticStateId<ScrollInfo> = StaticStateId::new_unique();