mirror of
https://github.com/danbulant/cushy
synced 2026-06-20 23:11:12 +00:00
Stack with premeasured content now work
This makes nested scroll areas work correctly.
This commit is contained in:
parent
80ba184c15
commit
947f1cd8a7
3 changed files with 61 additions and 20 deletions
18
examples/nested-scroll.rs
Normal file
18
examples/nested-scroll.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
use gooey::widget::MakeWidget;
|
||||
use gooey::Run;
|
||||
use kludgine::figures::units::Lp;
|
||||
|
||||
fn main() -> gooey::Result {
|
||||
include_str!("./nested-scroll.rs")
|
||||
.vertical_scroll()
|
||||
.height(Lp::inches(3))
|
||||
.and(
|
||||
include_str!("./canvas.rs")
|
||||
.vertical_scroll()
|
||||
.height(Lp::inches(3)),
|
||||
)
|
||||
.into_rows()
|
||||
.vertical_scroll()
|
||||
.expand()
|
||||
.run()
|
||||
}
|
||||
|
|
@ -296,7 +296,8 @@ struct Layout {
|
|||
total_weights: u32,
|
||||
allocated_space: (UPx, Lp),
|
||||
fractional: Vec<(LotId, u8)>,
|
||||
measured: Vec<LotId>,
|
||||
fit_to_content: Vec<LotId>,
|
||||
premeasured: Vec<LotId>,
|
||||
pub orientation: StackDirection,
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +317,8 @@ impl Layout {
|
|||
total_weights: 0,
|
||||
allocated_space: (UPx(0), Lp(0)),
|
||||
fractional: Vec::new(),
|
||||
measured: Vec::new(),
|
||||
fit_to_content: Vec::new(),
|
||||
premeasured: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,20 +333,23 @@ impl Layout {
|
|||
|
||||
match dimension {
|
||||
StackDimension::FitContent => {
|
||||
self.measured.retain(|&measured| measured != id);
|
||||
self.fit_to_content.retain(|&measured| measured != id);
|
||||
}
|
||||
StackDimension::Fractional { weight } => {
|
||||
self.fractional.retain(|(measured, _)| *measured != id);
|
||||
self.total_weights -= u32::from(weight);
|
||||
}
|
||||
StackDimension::Measured { min, .. } => match min {
|
||||
Dimension::Px(pixels) => {
|
||||
self.allocated_space.0 -= pixels.into_unsigned();
|
||||
StackDimension::Measured { min, .. } => {
|
||||
self.premeasured.retain(|&measured| measured != id);
|
||||
match min {
|
||||
Dimension::Px(pixels) => {
|
||||
self.allocated_space.0 -= pixels.into_unsigned();
|
||||
}
|
||||
Dimension::Lp(lp) => {
|
||||
self.allocated_space.1 -= lp;
|
||||
}
|
||||
}
|
||||
Dimension::Lp(lp) => {
|
||||
self.allocated_space.1 -= lp;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
dimension
|
||||
|
|
@ -364,7 +369,7 @@ impl Layout {
|
|||
let id = self.children.insert(index, child);
|
||||
let layout = match child {
|
||||
StackDimension::FitContent => {
|
||||
self.measured.push(id);
|
||||
self.fit_to_content.push(id);
|
||||
UPx(0)
|
||||
}
|
||||
StackDimension::Fractional { weight } => {
|
||||
|
|
@ -373,6 +378,7 @@ impl Layout {
|
|||
UPx(0)
|
||||
}
|
||||
StackDimension::Measured { min, .. } => {
|
||||
self.premeasured.push(id);
|
||||
match min {
|
||||
Dimension::Px(size) => self.allocated_space.0 += size.into_unsigned(),
|
||||
Dimension::Lp(size) => self.allocated_space.1 += size,
|
||||
|
|
@ -407,7 +413,7 @@ impl Layout {
|
|||
|
||||
// Measure the children that fit their content
|
||||
self.other = UPx(0);
|
||||
for &id in &self.measured {
|
||||
for &id in &self.fit_to_content {
|
||||
let index = self.children.index_of_id(id).expect("child not found");
|
||||
let (measured, other) = self.orientation.split_size(measure(
|
||||
index,
|
||||
|
|
@ -420,6 +426,20 @@ impl Layout {
|
|||
remaining = remaining.saturating_sub(measured);
|
||||
}
|
||||
|
||||
// Measure measure the "other" dimension for children that we know their size already.
|
||||
for &id in &self.premeasured {
|
||||
let index = self.children.index_of_id(id).expect("child not found");
|
||||
let (_, other) = self.orientation.split_size(measure(
|
||||
index,
|
||||
self.orientation.make_size(
|
||||
ConstraintLimit::Known(self.layouts[index].size),
|
||||
other_constraint,
|
||||
),
|
||||
!needs_final_layout,
|
||||
));
|
||||
self.other = self.other.max(other);
|
||||
}
|
||||
|
||||
// Measure the weighted children within the remaining space
|
||||
if self.total_weights > 0 {
|
||||
let space_per_weight = remaining / self.total_weights;
|
||||
|
|
|
|||
|
|
@ -868,7 +868,9 @@ where
|
|||
),
|
||||
kludgine,
|
||||
);
|
||||
let last_rendered_at = context.last_layout().expect("passed hit test");
|
||||
let Some(last_rendered_at) = context.last_layout() else {
|
||||
continue;
|
||||
};
|
||||
context.mouse_drag(location - last_rendered_at.origin, device_id, *button);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -886,11 +888,10 @@ where
|
|||
self.mouse_state.widget = None;
|
||||
for widget in self.root.tree.widgets_at_point(location) {
|
||||
let mut widget_context = context.for_other(&widget);
|
||||
let relative = location
|
||||
- widget_context
|
||||
.last_layout()
|
||||
.expect("passed hit test")
|
||||
.origin;
|
||||
let Some(widget_layout) = widget_context.last_layout() else {
|
||||
continue;
|
||||
};
|
||||
let relative = location - widget_layout.origin;
|
||||
|
||||
if widget_context.hit_test(relative) {
|
||||
widget_context.hover(relative);
|
||||
|
|
@ -970,8 +971,10 @@ where
|
|||
kludgine,
|
||||
),
|
||||
|context| {
|
||||
let relative =
|
||||
*location - context.last_layout().expect("passed hit test").origin;
|
||||
let Some(layout) = context.last_layout() else {
|
||||
return IGNORED;
|
||||
};
|
||||
let relative = *location - layout.origin;
|
||||
context.mouse_down(relative, device_id, button)
|
||||
},
|
||||
) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue