mirror of
https://github.com/danbulant/cushy
synced 2026-07-08 04:30:34 +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,
|
total_weights: u32,
|
||||||
allocated_space: (UPx, Lp),
|
allocated_space: (UPx, Lp),
|
||||||
fractional: Vec<(LotId, u8)>,
|
fractional: Vec<(LotId, u8)>,
|
||||||
measured: Vec<LotId>,
|
fit_to_content: Vec<LotId>,
|
||||||
|
premeasured: Vec<LotId>,
|
||||||
pub orientation: StackDirection,
|
pub orientation: StackDirection,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,7 +317,8 @@ impl Layout {
|
||||||
total_weights: 0,
|
total_weights: 0,
|
||||||
allocated_space: (UPx(0), Lp(0)),
|
allocated_space: (UPx(0), Lp(0)),
|
||||||
fractional: Vec::new(),
|
fractional: Vec::new(),
|
||||||
measured: Vec::new(),
|
fit_to_content: Vec::new(),
|
||||||
|
premeasured: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,20 +333,23 @@ impl Layout {
|
||||||
|
|
||||||
match dimension {
|
match dimension {
|
||||||
StackDimension::FitContent => {
|
StackDimension::FitContent => {
|
||||||
self.measured.retain(|&measured| measured != id);
|
self.fit_to_content.retain(|&measured| measured != id);
|
||||||
}
|
}
|
||||||
StackDimension::Fractional { weight } => {
|
StackDimension::Fractional { weight } => {
|
||||||
self.fractional.retain(|(measured, _)| *measured != id);
|
self.fractional.retain(|(measured, _)| *measured != id);
|
||||||
self.total_weights -= u32::from(weight);
|
self.total_weights -= u32::from(weight);
|
||||||
}
|
}
|
||||||
StackDimension::Measured { min, .. } => match min {
|
StackDimension::Measured { min, .. } => {
|
||||||
Dimension::Px(pixels) => {
|
self.premeasured.retain(|&measured| measured != id);
|
||||||
self.allocated_space.0 -= pixels.into_unsigned();
|
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
|
dimension
|
||||||
|
|
@ -364,7 +369,7 @@ impl Layout {
|
||||||
let id = self.children.insert(index, child);
|
let id = self.children.insert(index, child);
|
||||||
let layout = match child {
|
let layout = match child {
|
||||||
StackDimension::FitContent => {
|
StackDimension::FitContent => {
|
||||||
self.measured.push(id);
|
self.fit_to_content.push(id);
|
||||||
UPx(0)
|
UPx(0)
|
||||||
}
|
}
|
||||||
StackDimension::Fractional { weight } => {
|
StackDimension::Fractional { weight } => {
|
||||||
|
|
@ -373,6 +378,7 @@ impl Layout {
|
||||||
UPx(0)
|
UPx(0)
|
||||||
}
|
}
|
||||||
StackDimension::Measured { min, .. } => {
|
StackDimension::Measured { min, .. } => {
|
||||||
|
self.premeasured.push(id);
|
||||||
match min {
|
match min {
|
||||||
Dimension::Px(size) => self.allocated_space.0 += size.into_unsigned(),
|
Dimension::Px(size) => self.allocated_space.0 += size.into_unsigned(),
|
||||||
Dimension::Lp(size) => self.allocated_space.1 += size,
|
Dimension::Lp(size) => self.allocated_space.1 += size,
|
||||||
|
|
@ -407,7 +413,7 @@ impl Layout {
|
||||||
|
|
||||||
// Measure the children that fit their content
|
// Measure the children that fit their content
|
||||||
self.other = UPx(0);
|
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 index = self.children.index_of_id(id).expect("child not found");
|
||||||
let (measured, other) = self.orientation.split_size(measure(
|
let (measured, other) = self.orientation.split_size(measure(
|
||||||
index,
|
index,
|
||||||
|
|
@ -420,6 +426,20 @@ impl Layout {
|
||||||
remaining = remaining.saturating_sub(measured);
|
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
|
// Measure the weighted children within the remaining space
|
||||||
if self.total_weights > 0 {
|
if self.total_weights > 0 {
|
||||||
let space_per_weight = remaining / self.total_weights;
|
let space_per_weight = remaining / self.total_weights;
|
||||||
|
|
|
||||||
|
|
@ -868,7 +868,9 @@ where
|
||||||
),
|
),
|
||||||
kludgine,
|
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);
|
context.mouse_drag(location - last_rendered_at.origin, device_id, *button);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -886,11 +888,10 @@ where
|
||||||
self.mouse_state.widget = None;
|
self.mouse_state.widget = None;
|
||||||
for widget in self.root.tree.widgets_at_point(location) {
|
for widget in self.root.tree.widgets_at_point(location) {
|
||||||
let mut widget_context = context.for_other(&widget);
|
let mut widget_context = context.for_other(&widget);
|
||||||
let relative = location
|
let Some(widget_layout) = widget_context.last_layout() else {
|
||||||
- widget_context
|
continue;
|
||||||
.last_layout()
|
};
|
||||||
.expect("passed hit test")
|
let relative = location - widget_layout.origin;
|
||||||
.origin;
|
|
||||||
|
|
||||||
if widget_context.hit_test(relative) {
|
if widget_context.hit_test(relative) {
|
||||||
widget_context.hover(relative);
|
widget_context.hover(relative);
|
||||||
|
|
@ -970,8 +971,10 @@ where
|
||||||
kludgine,
|
kludgine,
|
||||||
),
|
),
|
||||||
|context| {
|
|context| {
|
||||||
let relative =
|
let Some(layout) = context.last_layout() else {
|
||||||
*location - context.last_layout().expect("passed hit test").origin;
|
return IGNORED;
|
||||||
|
};
|
||||||
|
let relative = *location - layout.origin;
|
||||||
context.mouse_down(relative, device_id, button)
|
context.mouse_down(relative, device_id, button)
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue