|
14 | 14 |
|
15 | 15 | //! A widget that arranges its children in a one-dimensional array.
|
16 | 16 |
|
| 17 | +use std::ops::Add; |
| 18 | + |
17 | 19 | use crate::debug_state::DebugState;
|
18 | 20 | use crate::kurbo::{common::FloatExt, Vec2};
|
19 | 21 | use crate::widget::prelude::*;
|
@@ -942,6 +944,108 @@ impl<T: Data> Widget<T> for Flex<T> {
|
942 | 944 | ..Default::default()
|
943 | 945 | }
|
944 | 946 | }
|
| 947 | + |
| 948 | + fn compute_max_intrinsic( |
| 949 | + &mut self, |
| 950 | + axis: Axis, |
| 951 | + ctx: &mut LayoutCtx, |
| 952 | + bc: &BoxConstraints, |
| 953 | + data: &T, |
| 954 | + env: &Env, |
| 955 | + ) -> f64 { |
| 956 | + if self.direction != axis { |
| 957 | + // Direction axis and sizing axis are different. |
| 958 | + // We compute max(child dim in cross axis). |
| 959 | + let mut max_size_on_cross_axis: f64 = 0.; |
| 960 | + let mut available_size_on_main_axis = self.direction.major(bc.max()); |
| 961 | + let mut total_flex = 0.; |
| 962 | + for child in self.children.iter_mut() { |
| 963 | + match child { |
| 964 | + Child::Fixed { widget, .. } => { |
| 965 | + let new_bc = bc |
| 966 | + .unbound_max(axis) |
| 967 | + .shrink_max_to(self.direction, available_size_on_main_axis); |
| 968 | + let size_on_main_axis = widget.widget_mut().compute_max_intrinsic( |
| 969 | + self.direction, |
| 970 | + ctx, |
| 971 | + &new_bc, |
| 972 | + data, |
| 973 | + env, |
| 974 | + ); |
| 975 | + let new_bc = new_bc.shrink_max_to(self.direction, size_on_main_axis); |
| 976 | + let size_on_cross_axis = widget |
| 977 | + .widget_mut() |
| 978 | + .compute_max_intrinsic(axis, ctx, &new_bc, data, env); |
| 979 | + available_size_on_main_axis -= size_on_main_axis; |
| 980 | + max_size_on_cross_axis = max_size_on_cross_axis.max(size_on_cross_axis); |
| 981 | + } |
| 982 | + Child::FixedSpacer(kv, _) => { |
| 983 | + let mut s = kv.resolve(env); |
| 984 | + if s < 0.0 { |
| 985 | + tracing::warn!("Length provided to fixed spacer was less than 0"); |
| 986 | + s = 0.; |
| 987 | + } |
| 988 | + max_size_on_cross_axis = max_size_on_cross_axis.max(s); |
| 989 | + } |
| 990 | + Child::Flex { flex, .. } | Child::FlexedSpacer(flex, _) => total_flex += *flex, |
| 991 | + } |
| 992 | + } |
| 993 | + let space_per_flex = available_size_on_main_axis / total_flex; |
| 994 | + |
| 995 | + if space_per_flex > 0.0 { |
| 996 | + for child in self.children.iter_mut() { |
| 997 | + // We ignore Child::FlexedSpacer because its cross size is irrelevant. |
| 998 | + // Its flex matters only on main axis. But here we are interested in cross size of |
| 999 | + // each flex child. |
| 1000 | + if let Child::Flex { widget, flex, .. } = child { |
| 1001 | + let main_axis_available_space = *flex * space_per_flex; |
| 1002 | + let new_bc = bc.shrink_max_to(axis, main_axis_available_space); |
| 1003 | + let size_on_cross_axis = widget |
| 1004 | + .widget_mut() |
| 1005 | + .compute_max_intrinsic(axis, ctx, &new_bc, data, env); |
| 1006 | + max_size_on_cross_axis = max_size_on_cross_axis.max(size_on_cross_axis); |
| 1007 | + } |
| 1008 | + } |
| 1009 | + } |
| 1010 | + max_size_on_cross_axis |
| 1011 | + } else { |
| 1012 | + // Direction axis and sizing axis are same. |
| 1013 | + // We compute total(child dim on that axis) |
| 1014 | + let mut total: f64 = 0.; |
| 1015 | + let mut max_flex_fraction: f64 = 0.; |
| 1016 | + let mut total_flex = 0.; |
| 1017 | + for child in self.children.iter_mut() { |
| 1018 | + match child { |
| 1019 | + Child::Fixed { widget, .. } => { |
| 1020 | + let s = widget |
| 1021 | + .widget_mut() |
| 1022 | + .compute_max_intrinsic(axis, ctx, bc, data, env); |
| 1023 | + total = total.add(s); |
| 1024 | + } |
| 1025 | + Child::Flex { widget, flex, .. } => { |
| 1026 | + let s = widget |
| 1027 | + .widget_mut() |
| 1028 | + .compute_max_intrinsic(axis, ctx, bc, data, env); |
| 1029 | + let flex_fraction = s / *flex; |
| 1030 | + total_flex += *flex; |
| 1031 | + max_flex_fraction = max_flex_fraction.max(flex_fraction); |
| 1032 | + } |
| 1033 | + Child::FixedSpacer(kv, _) => { |
| 1034 | + let mut s = kv.resolve(env); |
| 1035 | + if s < 0.0 { |
| 1036 | + tracing::warn!("Length provided to fixed spacer was less than 0"); |
| 1037 | + s = 0.; |
| 1038 | + } |
| 1039 | + total = total.add(s); |
| 1040 | + } |
| 1041 | + Child::FlexedSpacer(flex, _) => { |
| 1042 | + total_flex += *flex; |
| 1043 | + } |
| 1044 | + } |
| 1045 | + } |
| 1046 | + total + max_flex_fraction * total_flex |
| 1047 | + } |
| 1048 | + } |
945 | 1049 | }
|
946 | 1050 |
|
947 | 1051 | impl CrossAxisAlignment {
|
|
0 commit comments