Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ You can find its changes [documented below](#070---2021-01-01).

- Warn on unhandled Commands ([#1533] by [@Maan2003])
- `WindowDesc::new` takes the root widget directly instead of a closure ([#1559] by [@lassipulkkinen])
- Switch to trace-based logging ([#1562] by [@PoignardAzur])
- Spacers in `Flex` are now implemented by calculating the space in `Flex` instead of creating a widget for it ([#1584] by [@JAicewizard])

### Deprecated
Expand Down
132 changes: 87 additions & 45 deletions druid/src/widget/flex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,13 +541,16 @@ impl<T: Data> Flex<T> {
) {
let params = params.into();
let child = if params.flex == 0.0 {
Child::Fixed(WidgetPod::new(Box::new(child)), params.alignment)
Child::Fixed {
widget: WidgetPod::new(Box::new(child)),
alignment: params.alignment,
}
} else {
Child::Flex(
WidgetPod::new(Box::new(child)),
params.alignment,
params.flex,
)
Child::Flex {
widget: WidgetPod::new(Box::new(child)),
alignment: params.alignment,
flex: params.flex,
}
};
self.children.push(child);
}
Expand Down Expand Up @@ -585,34 +588,25 @@ impl<T: Data> Flex<T> {

impl<T: Data> Widget<T> for Flex<T> {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
for child in &mut self.children {
match child {
Child::Fixed(widget, _) | Child::Flex(widget, _, _) => {
widget.event(ctx, event, data, env)
}
_ => {}
for child in self.children.iter_mut().map(|x| x.widget_mut()) {
if let Some(widget) = child {
widget.event(ctx, event, data, env)
}
}
}

fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
for child in &mut self.children {
match child {
Child::Fixed(widget, _) | Child::Flex(widget, _, _) => {
widget.lifecycle(ctx, event, data, env)
}
_ => {}
for child in self.children.iter_mut().map(|x| x.widget_mut()) {
if let Some(widget) = child {
widget.lifecycle(ctx, event, data, env)
}
}
}

fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &T, data: &T, env: &Env) {
for child in &mut self.children {
match child {
Child::Fixed(widget, _) | Child::Flex(widget, _, _) => {
widget.update(ctx, data, env)
}
_ => {}
for child in self.children.iter_mut().map(|x| x.widget_mut()) {
if let Some(widget) = child {
widget.update(ctx, data, env)
}
}
}
Expand All @@ -634,7 +628,7 @@ impl<T: Data> Widget<T> for Flex<T> {
let mut flex_sum = 0.0;
for child in &mut self.children {
match child {
Child::Fixed(widget, alignment) => {
Child::Fixed { widget, alignment } => {
any_use_baseline &= *alignment == Some(CrossAxisAlignment::Baseline);

let child_bc =
Expand All @@ -644,11 +638,11 @@ impl<T: Data> Widget<T> for Flex<T> {
let baseline_offset = widget.baseline_offset();

if child_size.width.is_infinite() {
log::warn!("A non-Flex child has an infinite width.");
tracing::warn!("A non-Flex child has an infinite width.");
}

if child_size.height.is_infinite() {
log::warn!("A non-Flex child has an infinite height.");
tracing::warn!("A non-Flex child has an infinite height.");
}

major_non_flex += self.direction.major(child_size).expand();
Expand All @@ -661,7 +655,12 @@ impl<T: Data> Widget<T> for Flex<T> {
*calculated_siz = kv.resolve(env);
major_non_flex += *calculated_siz;
}
Child::Flex(_, _, flex) | Child::FlexedSpacer(flex, _) => flex_sum += *flex,
Child::Flex {
widget: _,
alignment: _,
flex,
}
| Child::FlexedSpacer(flex, _) => flex_sum += *flex,
}
}

Expand All @@ -674,7 +673,11 @@ impl<T: Data> Widget<T> for Flex<T> {
// Measure flex children.
for child in &mut self.children {
match child {
Child::Flex(widget, _, flex) => {
Child::Flex {
widget,
alignment: _,
flex,
} => {
let desired_major = (*flex) * px_per_flex + remainder;
let actual_major = desired_major.round();
remainder = desired_major - actual_major;
Expand Down Expand Up @@ -724,7 +727,12 @@ impl<T: Data> Widget<T> for Flex<T> {

for child in &mut self.children {
match child {
Child::Fixed(widget, alignment) | Child::Flex(widget, alignment, _) => {
Child::Fixed { widget, alignment }
| Child::Flex {
widget,
alignment,
flex: _,
} => {
let child_size = widget.layout_rect().size();
let alignment = alignment.unwrap_or(self.cross_alignment);
let child_minor_offset = match alignment {
Expand Down Expand Up @@ -791,17 +799,18 @@ impl<T: Data> Widget<T> for Flex<T> {

let baseline_offset = match self.direction {
Axis::Horizontal => max_below_baseline,
Axis::Vertical => self
.children
Axis::Vertical => (&self.children)
.last()
.map(|last| match last {
Child::Fixed(widget, _) | Child::Flex(widget, _, _) => {
.map(|last| {
let child = last.widget();
if let Some(widget) = child {
let child_bl = widget.baseline_offset();
let child_max_y = widget.layout_rect().max_y();
let extra_bottom_padding = my_size.height - child_max_y;
child_bl + extra_bottom_padding
} else {
0.0
}
_ => 0.0,
})
.unwrap_or(0.0),
};
Expand All @@ -811,10 +820,9 @@ impl<T: Data> Widget<T> for Flex<T> {
}

fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
for child in &mut self.children {
match child {
Child::Fixed(widget, _) | Child::Flex(widget, _, _) => widget.paint(ctx, data, env),
_ => {}
for child in self.children.iter_mut().map(|x| x.widget_mut()) {
if let Some(widget) = child {
widget.paint(ctx, data, env)
}
}

Expand Down Expand Up @@ -949,16 +957,50 @@ impl From<f64> for FlexParams {
}

enum Child<T> {
Fixed(WidgetPod<T, Box<dyn Widget<T>>>, Option<CrossAxisAlignment>),
Flex(
WidgetPod<T, Box<dyn Widget<T>>>,
Option<CrossAxisAlignment>,
f64,
),
Fixed {
widget: WidgetPod<T, Box<dyn Widget<T>>>,
alignment: Option<CrossAxisAlignment>,
},
Flex {
widget: WidgetPod<T, Box<dyn Widget<T>>>,
alignment: Option<CrossAxisAlignment>,
flex: f64,
},
FixedSpacer(KeyOrValue<f64>, f64),
FlexedSpacer(f64, f64),
}

impl<T> Child<T> {
fn widget_mut(&mut self) -> Option<&mut WidgetPod<T, Box<dyn Widget<T>>>> {
match self {
Child::Fixed {
widget,
alignment: _,
}
| Child::Flex {
widget,
alignment: _,
flex: _,
} => Some(widget),
_ => None,
}
}
fn widget(&self) -> Option<&WidgetPod<T, Box<dyn Widget<T>>>> {
match self {
Child::Fixed {
widget,
alignment: _,
}
| Child::Flex {
widget,
alignment: _,
flex: _,
} => Some(widget),
_ => None,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down