Layout alignment

This commit is contained in:
Olivier Goffart 2020-11-03 12:12:10 +01:00
parent fa077662c1
commit 4a182ef4d0
9 changed files with 152 additions and 19 deletions

View file

@ -283,6 +283,7 @@ using cbindgen_private::solve_box_layout;
using cbindgen_private::box_layout_info; using cbindgen_private::box_layout_info;
using cbindgen_private::solve_path_layout; using cbindgen_private::solve_path_layout;
using cbindgen_private::Rect; using cbindgen_private::Rect;
using cbindgen_private::LayoutAlignment;
inline LayoutInfo LayoutInfo::merge(const LayoutInfo &other) const { inline LayoutInfo LayoutInfo::merge(const LayoutInfo &other) const {
// Note: This "logic" is duplicated from LayoutInfo::merge in layout.rs. // Note: This "logic" is duplicated from LayoutInfo::merge in layout.rs.

View file

@ -187,6 +187,8 @@ they will be computed by the layout respecting the minimum and maximum sizes and
* **`padding`** (*length*): the padding within the layout. * **`padding`** (*length*): the padding within the layout.
* **`padding_left`**, **`padding_right`**, **`padding_top`** and **`padding_bottom`** (*length*): * **`padding_left`**, **`padding_right`**, **`padding_top`** and **`padding_bottom`** (*length*):
override the padding in specific sides. override the padding in specific sides.
* **`alignment`** (*FIXME enum*): Can be one of `stretch`, `center`, `start`, `end`,
`space_between`, `space_around`. Defaults to `stretch`. Matches the CSS flex.
## Example ## Example

View file

@ -1679,11 +1679,18 @@ impl crate::layout::gen::Language for CppLanguageLayoutGen {
component, component,
); );
let alignment = if let Some(nr) = &box_layout.geometry.alignment {
format!("{}.get()", access_named_reference(nr, component, "self"))
} else {
"{}".into()
};
LayoutTreeItem::BoxLayout { LayoutTreeItem::BoxLayout {
is_horizontal: box_layout.is_horizontal, is_horizontal: box_layout.is_horizontal,
geometry: &box_layout.geometry, geometry: &box_layout.geometry,
spacing, spacing,
padding, padding,
alignment,
var_creation_code: creation_code.join("\n"), var_creation_code: creation_code.join("\n"),
cell_ref_variable, cell_ref_variable,
} }
@ -1703,11 +1710,12 @@ impl<'a> LayoutTreeItem<'a> {
spacing, spacing,
cell_ref_variable, cell_ref_variable,
padding, padding,
alignment,
is_horizontal, is_horizontal,
.. ..
} => format!( } => format!(
"sixtyfps::box_layout_info(&{}, {}, &{}, {})", "sixtyfps::box_layout_info(&{}, {}, &{}, {}, {})",
cell_ref_variable, spacing, padding, is_horizontal cell_ref_variable, spacing, padding, alignment, is_horizontal
), ),
LayoutTreeItem::PathLayout(_) => "{/*layout_info for path not implemented*/}".into(), LayoutTreeItem::PathLayout(_) => "{/*layout_info for path not implemented*/}".into(),
} }
@ -1822,19 +1830,21 @@ impl<'a> LayoutTreeItem<'a> {
spacing, spacing,
cell_ref_variable, cell_ref_variable,
padding, padding,
alignment,
is_horizontal, is_horizontal,
.. ..
} => { } => {
code_stream.push(" { ".into()); code_stream.push(" { ".into());
code_stream.push(" sixtyfps::BoxLayoutData box { ".into()); code_stream.push(" sixtyfps::BoxLayoutData box { ".into());
code_stream.push(format!( code_stream.push(format!(
" {w}, {h}, {x}, {y}, {s}, &{p},", " {w}, {h}, {x}, {y}, {s}, &{p}, {a},",
w = layout_prop(&geometry.rect.width_reference), w = layout_prop(&geometry.rect.width_reference),
h = layout_prop(&geometry.rect.height_reference), h = layout_prop(&geometry.rect.height_reference),
x = layout_prop(&geometry.rect.x_reference), x = layout_prop(&geometry.rect.x_reference),
y = layout_prop(&geometry.rect.y_reference), y = layout_prop(&geometry.rect.y_reference),
s = spacing, s = spacing,
p = padding, p = padding,
a = alignment
)); ));
code_stream.push(format!(" {cv}", cv = cell_ref_variable)); code_stream.push(format!(" {cv}", cv = cell_ref_variable));
code_stream.push(" };".to_owned()); code_stream.push(" };".to_owned());

View file

@ -47,6 +47,10 @@ fn rust_type(
let inner = rust_type(&o, span)?; let inner = rust_type(&o, span)?;
Ok(quote!(sixtyfps::re_exports::ModelHandle<#inner>)) Ok(quote!(sixtyfps::re_exports::ModelHandle<#inner>))
} }
Type::Enumeration(e) => {
let e = format_ident!("{}", e.name);
Ok(quote!(sixtyfps::re_exports::#e))
}
_ => Err(CompilerDiagnostic { _ => Err(CompilerDiagnostic {
message: format!("Cannot map property type {} to Rust", ty), message: format!("Cannot map property type {} to Rust", ty),
span: span.clone(), span: span.clone(),
@ -1513,6 +1517,13 @@ impl crate::layout::gen::Language for RustLanguageLayoutGen {
let (padding, spacing, spacing_creation_code) = let (padding, spacing, spacing_creation_code) =
generate_layout_padding_and_spacing(&layout_tree, &box_layout.geometry, component); generate_layout_padding_and_spacing(&layout_tree, &box_layout.geometry, component);
let alignment = if let Some(expr) = &box_layout.geometry.alignment {
let p = access_named_reference(expr, component, quote!(_self));
quote!(#p.get())
} else {
quote!(::core::default::Default::default())
};
LayoutTreeItem::BoxLayout { LayoutTreeItem::BoxLayout {
is_horizontal: box_layout.is_horizontal, is_horizontal: box_layout.is_horizontal,
geometry: &box_layout.geometry, geometry: &box_layout.geometry,
@ -1520,6 +1531,7 @@ impl crate::layout::gen::Language for RustLanguageLayoutGen {
cell_ref_variable: quote!(#cell_ref_variable), cell_ref_variable: quote!(#cell_ref_variable),
spacing, spacing,
padding, padding,
alignment,
} }
.into() .into()
} }
@ -1537,10 +1549,11 @@ impl<'a> LayoutTreeItem<'a> {
cell_ref_variable, cell_ref_variable,
spacing, spacing,
padding, padding,
alignment,
is_horizontal, is_horizontal,
.. ..
} => { } => {
quote!(box_layout_info(&Slice::from_slice(&#cell_ref_variable), #spacing, #padding, #is_horizontal)) quote!(box_layout_info(&Slice::from_slice(&#cell_ref_variable), #spacing, #padding, #alignment, #is_horizontal))
} }
LayoutTreeItem::PathLayout(_) => quote!(todo!("layout_info for PathLayout in rust.rs")), LayoutTreeItem::PathLayout(_) => quote!(todo!("layout_info for PathLayout in rust.rs")),
} }
@ -1629,7 +1642,7 @@ impl<'a> LayoutTreeItem<'a> {
let p = access_named_reference(nr, component, quote!(_self)); let p = access_named_reference(nr, component, quote!(_self));
quote!(#p.get()) quote!(#p.get())
} else { } else {
quote!(0.) quote!(::core::default::Default::default())
} }
}; };
match self { match self {
@ -1645,8 +1658,8 @@ impl<'a> LayoutTreeItem<'a> {
solve_grid_layout(&GridLayoutData { solve_grid_layout(&GridLayoutData {
width: #width, width: #width,
height: #height, height: #height,
x: #x_pos as _, x: #x_pos,
y: #y_pos as _, y: #y_pos,
cells: Slice::from_slice(&#cell_ref_variable), cells: Slice::from_slice(&#cell_ref_variable),
spacing: #spacing, spacing: #spacing,
padding: #padding, padding: #padding,
@ -1658,6 +1671,7 @@ impl<'a> LayoutTreeItem<'a> {
cell_ref_variable, cell_ref_variable,
spacing, spacing,
padding, padding,
alignment,
is_horizontal, is_horizontal,
.. ..
} => { } => {
@ -1670,11 +1684,12 @@ impl<'a> LayoutTreeItem<'a> {
solve_box_layout(&BoxLayoutData { solve_box_layout(&BoxLayoutData {
width: #width, width: #width,
height: #height, height: #height,
x: #x_pos as _, x: #x_pos,
y: #y_pos as _, y: #y_pos,
cells: Slice::from_slice(&#cell_ref_variable), cells: Slice::from_slice(&#cell_ref_variable),
spacing: #spacing, spacing: #spacing,
padding: #padding, padding: #padding,
alignment: #alignment
}, #is_horizontal); }, #is_horizontal);
}); });
} }

View file

@ -214,6 +214,7 @@ impl Padding {
pub struct LayoutGeometry { pub struct LayoutGeometry {
pub rect: LayoutRect, pub rect: LayoutRect,
pub spacing: Option<NamedReference>, pub spacing: Option<NamedReference>,
pub alignment: Option<NamedReference>,
pub padding: Padding, pub padding: Padding,
} }
@ -221,6 +222,7 @@ impl LayoutGeometry {
fn visit_named_references(&mut self, visitor: &mut impl FnMut(&mut NamedReference)) { fn visit_named_references(&mut self, visitor: &mut impl FnMut(&mut NamedReference)) {
self.rect.visit_named_references(visitor); self.rect.visit_named_references(visitor);
self.spacing.as_mut().map(|e| visitor(&mut *e)); self.spacing.as_mut().map(|e| visitor(&mut *e));
self.alignment.as_mut().map(|e| visitor(&mut *e));
self.padding.visit_named_references(visitor); self.padding.visit_named_references(visitor);
} }
} }
@ -254,6 +256,7 @@ impl LayoutGeometry {
pub fn new(rect: LayoutRect, layout_element: &ElementRc) -> Self { pub fn new(rect: LayoutRect, layout_element: &ElementRc) -> Self {
let padding = || binding_reference(layout_element, "padding"); let padding = || binding_reference(layout_element, "padding");
let spacing = binding_reference(layout_element, "spacing"); let spacing = binding_reference(layout_element, "spacing");
let alignment = binding_reference(layout_element, "alignment");
init_fake_property(layout_element, "width", || rect.width_reference.clone()); init_fake_property(layout_element, "width", || rect.width_reference.clone());
init_fake_property(layout_element, "height", || rect.height_reference.clone()); init_fake_property(layout_element, "height", || rect.height_reference.clone());
@ -271,7 +274,7 @@ impl LayoutGeometry {
bottom: binding_reference(layout_element, "padding_bottom").or_else(padding), bottom: binding_reference(layout_element, "padding_bottom").or_else(padding),
}; };
Self { rect, spacing, padding } Self { rect, spacing, padding, alignment }
} }
} }
@ -377,6 +380,7 @@ pub mod gen {
geometry: &'a LayoutGeometry, geometry: &'a LayoutGeometry,
spacing: L::CompiledCode, spacing: L::CompiledCode,
padding: L::CompiledCode, padding: L::CompiledCode,
alignment: L::CompiledCode,
var_creation_code: L::CompiledCode, var_creation_code: L::CompiledCode,
cell_ref_variable: L::CompiledCode, cell_ref_variable: L::CompiledCode,
is_horizontal: bool, is_horizontal: bool,

View file

@ -96,6 +96,10 @@ impl TypeRegister {
declare_enum("TextHorizontalAlignment", &["align_left", "align_center", "align_right"]); declare_enum("TextHorizontalAlignment", &["align_left", "align_center", "align_right"]);
let text_vertical_alignment = let text_vertical_alignment =
declare_enum("TextVerticalAlignment", &["align_top", "align_center", "align_bottom"]); declare_enum("TextVerticalAlignment", &["align_top", "align_center", "align_bottom"]);
let layout_alignment = declare_enum(
"LayoutAlignment",
&["stretch", "center", "start", "end", "space_between", "space_around"],
);
let native_class_with_member_functions = let native_class_with_member_functions =
|tr: &mut TypeRegister, |tr: &mut TypeRegister,
@ -296,9 +300,15 @@ impl TypeRegister {
let mut horizontal_layout = let mut horizontal_layout =
BuiltinElement::new(Rc::new(NativeClass::new("HorizontalLayout"))); BuiltinElement::new(Rc::new(NativeClass::new("HorizontalLayout")));
horizontal_layout.properties.insert("spacing".to_owned(), Type::Length); horizontal_layout.properties.insert("spacing".to_owned(), Type::Length);
horizontal_layout
.properties
.insert("alignment".to_owned(), Type::Enumeration(layout_alignment.clone()));
register.insert_type(Type::Builtin(Rc::new(horizontal_layout))); register.insert_type(Type::Builtin(Rc::new(horizontal_layout)));
let mut vertical_layout = BuiltinElement::new(Rc::new(NativeClass::new("VerticalLayout"))); let mut vertical_layout = BuiltinElement::new(Rc::new(NativeClass::new("VerticalLayout")));
vertical_layout.properties.insert("spacing".to_owned(), Type::Length); vertical_layout.properties.insert("spacing".to_owned(), Type::Length);
vertical_layout
.properties
.insert("alignment".to_owned(), Type::Enumeration(layout_alignment));
register.insert_type(Type::Builtin(Rc::new(vertical_layout))); register.insert_type(Type::Builtin(Rc::new(vertical_layout)));
let mut path_class = NativeClass::new("Path"); let mut path_class = NativeClass::new("Path");

View file

@ -382,6 +382,51 @@ pub extern "C" fn grid_layout_info<'a>(
} }
} }
/// Enum representing the alignment property of a BoxLayout or HorizontalLayout
#[derive(Copy, Clone, Debug, PartialEq, strum_macros::EnumString, strum_macros::Display)]
#[repr(C)]
#[allow(non_camel_case_types)]
pub enum LayoutAlignment {
stretch,
center,
start,
end,
space_between,
space_around,
}
impl Default for LayoutAlignment {
fn default() -> Self {
Self::stretch
}
}
impl From<LayoutAlignment> for stretch::style::JustifyContent {
fn from(a: LayoutAlignment) -> Self {
match a {
LayoutAlignment::stretch => Self::FlexStart,
LayoutAlignment::center => Self::Center,
LayoutAlignment::start => Self::FlexStart,
LayoutAlignment::end => Self::FlexEnd,
LayoutAlignment::space_between => Self::SpaceBetween,
LayoutAlignment::space_around => Self::SpaceAround,
}
}
}
impl From<LayoutAlignment> for stretch::style::AlignContent {
fn from(a: LayoutAlignment) -> Self {
match a {
LayoutAlignment::stretch => Self::Stretch,
LayoutAlignment::center => Self::Center,
LayoutAlignment::start => Self::FlexStart,
LayoutAlignment::end => Self::FlexEnd,
LayoutAlignment::space_between => Self::SpaceBetween,
LayoutAlignment::space_around => Self::SpaceAround,
}
}
}
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
/// The BoxLayoutData is used to represent both a Horizontal and Vertical layout. /// The BoxLayoutData is used to represent both a Horizontal and Vertical layout.
@ -394,6 +439,7 @@ pub struct BoxLayoutData<'a> {
pub y: Coord, pub y: Coord,
pub spacing: Coord, pub spacing: Coord,
pub padding: &'a Padding, pub padding: &'a Padding,
pub alignment: LayoutAlignment,
pub cells: Slice<'a, BoxLayoutCellData<'a>>, pub cells: Slice<'a, BoxLayoutCellData<'a>>,
} }
@ -418,10 +464,10 @@ pub extern "C" fn solve_box_layout(data: &BoxLayoutData, is_horizontal: bool) {
let box_style = stretch::style::Style { let box_style = stretch::style::Style {
size: Size { width: Dimension::Percent(1.), height: Dimension::Percent(1.) }, size: Size { width: Dimension::Percent(1.), height: Dimension::Percent(1.) },
flex_grow: 1.,
display: Display::Flex,
flex_direction: if is_horizontal { FlexDirection::Row } else { FlexDirection::Column }, flex_direction: if is_horizontal { FlexDirection::Row } else { FlexDirection::Column },
flex_basis: Dimension::Percent(1.), flex_basis: Dimension::Percent(1.),
justify_content: data.alignment.into(),
align_content: data.alignment.into(),
..Default::default() ..Default::default()
}; };
@ -469,7 +515,13 @@ pub extern "C" fn solve_box_layout(data: &BoxLayoutData, is_horizontal: bool) {
let cell_style = Style { let cell_style = Style {
min_size, min_size,
max_size, max_size,
flex_grow: if let Some(s) = smaller_strecth { stretch_factor(cell) / s } else { 1. }, flex_grow: if data.alignment != LayoutAlignment::stretch {
0.
} else if let Some(s) = smaller_strecth {
stretch_factor(cell) / s
} else {
1.
},
flex_basis: if is_horizontal { min_size.width } else { min_size.height }, flex_basis: if is_horizontal { min_size.width } else { min_size.height },
margin, margin,
align_self: AlignSelf::Stretch, align_self: AlignSelf::Stretch,
@ -509,6 +561,7 @@ pub extern "C" fn box_layout_info<'a>(
cells: &Slice<'a, BoxLayoutCellData<'a>>, cells: &Slice<'a, BoxLayoutCellData<'a>>,
spacing: Coord, spacing: Coord,
padding: &Padding, padding: &Padding,
alignment: LayoutAlignment,
is_horizontal: bool, is_horizontal: bool,
) -> LayoutInfo { ) -> LayoutInfo {
let count = cells.len(); let count = cells.len();
@ -516,6 +569,7 @@ pub extern "C" fn box_layout_info<'a>(
return LayoutInfo { max_width: 0., max_height: 0., ..LayoutInfo::default() }; return LayoutInfo { max_width: 0., max_height: 0., ..LayoutInfo::default() };
}; };
let order_float = |a: &Coord, b: &Coord| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal); let order_float = |a: &Coord, b: &Coord| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal);
let is_stretch = alignment == LayoutAlignment::stretch;
if is_horizontal { if is_horizontal {
let extra_w = padding.left + padding.right + spacing * (count - 1) as Coord; let extra_w = padding.left + padding.right + spacing * (count - 1) as Coord;
@ -527,7 +581,11 @@ pub extern "C" fn box_layout_info<'a>(
+ padding.top + padding.top
+ padding.bottom; + padding.bottom;
let min_width = cells.iter().map(|c| c.constraint.min_width).sum::<Coord>() + extra_w; let min_width = cells.iter().map(|c| c.constraint.min_width).sum::<Coord>() + extra_w;
let max_width = cells.iter().map(|c| c.constraint.max_width).sum::<Coord>() + extra_w; let max_width = if is_stretch {
cells.iter().map(|c| c.constraint.max_width).sum::<Coord>() + extra_w
} else {
f32::MAX
};
let horizontal_stretch = cells.iter().map(|c| c.constraint.horizontal_stretch).sum::<f32>(); let horizontal_stretch = cells.iter().map(|c| c.constraint.horizontal_stretch).sum::<f32>();
let vertical_stretch = let vertical_stretch =
cells.iter().map(|c| c.constraint.vertical_stretch).min_by(order_float).unwrap(); cells.iter().map(|c| c.constraint.vertical_stretch).min_by(order_float).unwrap();
@ -549,7 +607,11 @@ pub extern "C" fn box_layout_info<'a>(
+ padding.left + padding.left
+ padding.right; + padding.right;
let min_height = cells.iter().map(|c| c.constraint.min_height).sum::<Coord>() + extra_h; let min_height = cells.iter().map(|c| c.constraint.min_height).sum::<Coord>() + extra_h;
let max_height = cells.iter().map(|c| c.constraint.max_height).sum::<Coord>() + extra_h; let max_height = if is_stretch {
cells.iter().map(|c| c.constraint.max_height).sum::<Coord>() + extra_h
} else {
f32::MAX
};
let horizontal_stretch = let horizontal_stretch =
cells.iter().map(|c| c.constraint.horizontal_stretch).min_by(order_float).unwrap(); cells.iter().map(|c| c.constraint.horizontal_stretch).min_by(order_float).unwrap();
let vertical_stretch = cells.iter().map(|c| c.constraint.vertical_stretch).sum::<f32>(); let vertical_stretch = cells.iter().map(|c| c.constraint.vertical_stretch).sum::<f32>();

View file

@ -593,7 +593,7 @@ fn generate_component<'id>(
if decl.is_alias.is_some() { if decl.is_alias.is_some() {
continue; continue;
} }
let (prop, type_info) = match decl.property_type { let (prop, type_info) = match &decl.property_type {
Type::Float32 => animated_property_info::<f32>(), Type::Float32 => animated_property_info::<f32>(),
Type::Int32 => animated_property_info::<i32>(), Type::Int32 => animated_property_info::<i32>(),
Type::String => property_info::<SharedString>(), Type::String => property_info::<SharedString>(),
@ -611,6 +611,16 @@ fn generate_component<'id>(
Type::Object { .. } => property_info::<eval::Value>(), Type::Object { .. } => property_info::<eval::Value>(),
Type::Array(_) => property_info::<eval::Value>(), Type::Array(_) => property_info::<eval::Value>(),
Type::Percent => property_info::<f32>(), Type::Percent => property_info::<f32>(),
Type::Enumeration(e) => match e.name.as_ref() {
"LayoutAlignment" => property_info::<sixtyfps_corelib::layout::LayoutAlignment>(),
"TextHorizontalAlignment" => {
property_info::<sixtyfps_corelib::items::TextHorizontalAlignment>()
}
"TextVerticalAlignment" => {
property_info::<sixtyfps_corelib::items::TextVerticalAlignment>()
}
_ => panic!("unkown enum"),
},
_ => panic!("bad type"), _ => panic!("bad type"),
}; };
custom_properties.insert( custom_properties.insert(
@ -970,7 +980,11 @@ impl<'a> BoxLayoutCellTmpData<'a> {
#[derive(derive_more::From)] #[derive(derive_more::From)]
enum LayoutTreeItem<'a> { enum LayoutTreeItem<'a> {
GridLayout(LayoutWithCells<'a, GridLayoutCellData<'a>>), GridLayout(LayoutWithCells<'a, GridLayoutCellData<'a>>),
BoxLayout(LayoutWithCells<'a, BoxLayoutCellTmpData<'a>>, bool), BoxLayout(
LayoutWithCells<'a, BoxLayoutCellTmpData<'a>>,
bool,
sixtyfps_corelib::layout::LayoutAlignment,
),
PathLayout(&'a PathLayout), PathLayout(&'a PathLayout),
} }
@ -982,12 +996,13 @@ impl<'a> LayoutTreeItem<'a> {
grid_layout.spacing, grid_layout.spacing,
&grid_layout.padding, &grid_layout.padding,
), ),
LayoutTreeItem::BoxLayout(box_layout, is_horizontal) => { LayoutTreeItem::BoxLayout(box_layout, is_horizontal, alignment) => {
let cells = BoxLayoutCellTmpData::into_cells(&box_layout.cells); let cells = BoxLayoutCellTmpData::into_cells(&box_layout.cells);
box_layout_info( box_layout_info(
&Slice::from(cells.as_slice()), &Slice::from(cells.as_slice()),
box_layout.spacing, box_layout.spacing,
&box_layout.padding, &box_layout.padding,
*alignment,
*is_horizontal, *is_horizontal,
) )
} }
@ -1154,9 +1169,21 @@ fn collect_layouts_recursively<'a, 'b>(
top: box_layout.geometry.padding.top.as_ref().map_or(0., expr_eval), top: box_layout.geometry.padding.top.as_ref().map_or(0., expr_eval),
bottom: box_layout.geometry.padding.bottom.as_ref().map_or(0., expr_eval), bottom: box_layout.geometry.padding.bottom.as_ref().map_or(0., expr_eval),
}; };
let alignment = box_layout
.geometry
.alignment
.as_ref()
.map(|nr| {
eval::load_property(component, &nr.element.upgrade().unwrap(), &nr.name)
.unwrap()
.try_into()
.unwrap_or_default()
})
.unwrap_or_default();
layout_tree.push(LayoutTreeItem::BoxLayout( layout_tree.push(LayoutTreeItem::BoxLayout(
LayoutWithCells { geometry: &box_layout.geometry, cells, spacing, padding }, LayoutWithCells { geometry: &box_layout.geometry, cells, spacing, padding },
box_layout.is_horizontal, box_layout.is_horizontal,
alignment,
)); ));
} }
Layout::PathLayout(layout) => layout_tree.push(layout.into()), Layout::PathLayout(layout) => layout_tree.push(layout.into()),
@ -1187,7 +1214,7 @@ impl<'a> LayoutTreeItem<'a> {
cells: Slice::from(grid_layout.cells.as_slice()), cells: Slice::from(grid_layout.cells.as_slice()),
}); });
} }
Self::BoxLayout(box_layout, is_horizontal) => { Self::BoxLayout(box_layout, is_horizontal, alignment) => {
let cells = BoxLayoutCellTmpData::into_cells(&box_layout.cells); let cells = BoxLayoutCellTmpData::into_cells(&box_layout.cells);
solve_box_layout( solve_box_layout(
&BoxLayoutData { &BoxLayoutData {
@ -1198,6 +1225,7 @@ impl<'a> LayoutTreeItem<'a> {
spacing: box_layout.spacing, spacing: box_layout.spacing,
padding: &box_layout.padding, padding: &box_layout.padding,
cells: Slice::from(cells.as_slice()), cells: Slice::from(cells.as_slice()),
alignment: *alignment,
}, },
*is_horizontal, *is_horizontal,
); );

View file

@ -210,6 +210,7 @@ macro_rules! declare_value_enum_conversion {
declare_value_enum_conversion!(corelib::items::TextHorizontalAlignment, TextHorizontalAlignment); declare_value_enum_conversion!(corelib::items::TextHorizontalAlignment, TextHorizontalAlignment);
declare_value_enum_conversion!(corelib::items::TextVerticalAlignment, TextVerticalAlignment); declare_value_enum_conversion!(corelib::items::TextVerticalAlignment, TextVerticalAlignment);
declare_value_enum_conversion!(corelib::layout::LayoutAlignment, LayoutAlignment);
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum ComponentInstance<'a, 'id> { enum ComponentInstance<'a, 'id> {