Expand and stack fixes

This commit is contained in:
Jonathan Johnson 2023-11-29 11:43:52 -08:00
parent 589c3dbc7f
commit 9146c920ac
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
3 changed files with 38 additions and 26 deletions

View file

@ -34,7 +34,7 @@ use crate::styles::{
}; };
use crate::tree::Tree; use crate::tree::Tree;
use crate::utils::IgnorePoison; use crate::utils::IgnorePoison;
use crate::value::{IntoDynamic, IntoValue, Validation, Value}; use crate::value::{Dynamic, IntoDynamic, IntoValue, Validation, Value};
use crate::widgets::checkbox::{Checkable, CheckboxState}; use crate::widgets::checkbox::{Checkable, CheckboxState};
use crate::widgets::{ use crate::widgets::{
Align, Button, Checkbox, Collapse, Container, Expand, Resize, Scroll, Space, Stack, Style, Align, Button, Checkbox, Collapse, Container, Expand, Resize, Scroll, Space, Stack, Style,
@ -880,7 +880,7 @@ pub trait MakeWidget: Sized {
/// Expands `self` to grow to fill its parent vertically. /// Expands `self` to grow to fill its parent vertically.
#[must_use] #[must_use]
fn expand_vertically(self) -> Expand { fn expand_vertically(self) -> Expand {
Expand::horizontal(self) Expand::vertical(self)
} }
/// Resizes `self` to `size`. /// Resizes `self` to `size`.
@ -1647,6 +1647,20 @@ impl Children {
} }
} }
impl Dynamic<Children> {
/// Returns `self` as a vertical [`Stack`] of rows.
#[must_use]
pub fn into_rows(self) -> Stack {
Stack::rows(self)
}
/// Returns `self` as a horizontal [`Stack`] of columns.
#[must_use]
pub fn into_columns(self) -> Stack {
Stack::columns(self)
}
}
impl<W> FromIterator<W> for Children impl<W> FromIterator<W> for Children
where where
W: MakeWidget, W: MakeWidget,

View file

@ -15,7 +15,7 @@ pub struct Expand {
child: WidgetRef, child: WidgetRef,
} }
#[derive(Debug)] #[derive(Debug, Clone, Copy)]
enum ExpandKind { enum ExpandKind {
Weighted(u8), Weighted(u8),
Horizontal, Horizontal,
@ -84,10 +84,11 @@ impl Expand {
} }
#[must_use] #[must_use]
pub(crate) fn weight(&self) -> Option<u8> { pub(crate) fn weight(&self, vertical: bool) -> Option<u8> {
match self.kind { match (self.kind, vertical) {
ExpandKind::Weighted(weight) => Some(weight), (ExpandKind::Weighted(weight), _) => Some(weight),
ExpandKind::Horizontal | ExpandKind::Vertical => None, (ExpandKind::Horizontal, false) | (ExpandKind::Vertical, true) => Some(1),
(ExpandKind::Horizontal | ExpandKind::Vertical, _) => None,
} }
} }
} }
@ -123,10 +124,10 @@ impl WrapperWidget for Expand {
available_space available_space
.width .width
.fit_measured(size.width, context.gfx.scale()), .fit_measured(size.width, context.gfx.scale()),
size.height, size.height.min(available_space.height.max()),
), ),
ExpandKind::Vertical => ( ExpandKind::Vertical => (
size.width, size.width.min(available_space.width.max()),
available_space available_space
.height .height
.fit_measured(size.height, context.gfx.scale()), .fit_measured(size.height, context.gfx.scale()),

View file

@ -22,8 +22,7 @@ use crate::ConstraintLimit;
/// [direction](StackDirection). /// [direction](StackDirection).
#[derive(Debug)] #[derive(Debug)]
pub struct Stack { pub struct Stack {
/// The direction to display the children using. direction: StackDirection,
pub direction: Value<StackDirection>,
/// The children widgets that belong to this array. /// The children widgets that belong to this array.
pub children: Value<Children>, pub children: Value<Children>,
layout: Layout, layout: Layout,
@ -34,18 +33,11 @@ pub struct Stack {
impl Stack { impl Stack {
/// Returns a new widget with the given direction and widgets. /// Returns a new widget with the given direction and widgets.
pub fn new( pub fn new(direction: StackDirection, widgets: impl IntoValue<Children>) -> Self {
direction: impl IntoValue<StackDirection>,
widgets: impl IntoValue<Children>,
) -> Self {
let direction = direction.into_value();
let initial_direction = direction.get();
Self { Self {
direction, direction,
children: widgets.into_value(), children: widgets.into_value(),
layout: Layout::new(initial_direction), layout: Layout::new(direction),
layout_generation: None, layout_generation: None,
synced_children: Vec::new(), synced_children: Vec::new(),
} }
@ -63,6 +55,7 @@ impl Stack {
fn synchronize_children(&mut self, context: &mut EventContext<'_, '_>) { fn synchronize_children(&mut self, context: &mut EventContext<'_, '_>) {
let current_generation = self.children.generation(); let current_generation = self.children.generation();
self.children.invalidate_when_changed(context);
if current_generation.map_or_else( if current_generation.map_or_else(
|| self.children.map(Children::len) != self.layout.children.len(), || self.children.map(Children::len) != self.layout.children.len(),
|gen| Some(gen) != self.layout_generation, |gen| Some(gen) != self.layout_generation,
@ -89,10 +82,12 @@ impl Stack {
} else { } else {
// This is a brand new child. // This is a brand new child.
let guard = widget.lock(); let guard = widget.lock();
let (mut widget, dimension) = if let Some((weight, expand)) = guard let (mut widget, dimension) = if let Some((weight, expand)) =
.downcast_ref::<Expand>() guard.downcast_ref::<Expand>().and_then(|expand| {
.and_then(|expand| expand.weight().map(|weight| (weight, expand))) expand
{ .weight(self.direction.orientation == StackOrientation::Row)
.map(|weight| (weight, expand))
}) {
( (
expand.child().clone(), expand.child().clone(),
StackDimension::Fractional { weight }, StackDimension::Fractional { weight },
@ -429,8 +424,10 @@ impl Layout {
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,
self.orientation self.orientation.make_size(
.make_size(ConstraintLimit::SizeToFit(remaining), other_constraint), ConstraintLimit::SizeToFit(available_space),
other_constraint,
),
!needs_final_layout, !needs_final_layout,
)); ));
self.layouts[index].size = measured; self.layouts[index].size = measured;