Skip to content

Commit 04f0bdc

Browse files
committed
Lay out grids at runtime rather than at compile time
This includes support for row and col properties to be expressions rather than just constants. However this doesn't yet include re-layouting when those properties change value.
1 parent 188f940 commit 04f0bdc

File tree

10 files changed

+373
-137
lines changed

10 files changed

+373
-137
lines changed

api/cpp/include/slint.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,19 @@ inline SharedVector<float> solve_box_layout(const cbindgen_private::BoxLayoutDat
123123
return result;
124124
}
125125

126-
inline SharedVector<float> solve_grid_layout(const cbindgen_private::GridLayoutData &data)
126+
inline SharedVector<float> solve_grid_layout(const cbindgen_private::GridLayoutData &data,
127+
cbindgen_private::Orientation orientation)
127128
{
128129
SharedVector<float> result;
129-
cbindgen_private::slint_solve_grid_layout(&data, &result);
130+
cbindgen_private::slint_solve_grid_layout(&data, orientation, &result);
130131
return result;
131132
}
132133

133134
inline cbindgen_private::LayoutInfo
134135
grid_layout_info(cbindgen_private::Slice<cbindgen_private::GridLayoutCellData> cells, float spacing,
135-
const cbindgen_private::Padding &padding)
136+
const cbindgen_private::Padding &padding, cbindgen_private::Orientation o)
136137
{
137-
return cbindgen_private::slint_grid_layout_info(cells, spacing, &padding);
138+
return cbindgen_private::slint_grid_layout_info(cells, spacing, &padding, o);
138139
}
139140

140141
inline cbindgen_private::LayoutInfo

internal/compiler/layout.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,18 +278,19 @@ impl LayoutConstraints {
278278
/// An element in a GridLayout
279279
#[derive(Debug, Clone)]
280280
pub struct GridLayoutElement {
281-
pub col: u16,
282-
pub row: u16,
281+
pub new_row: bool,
282+
pub col_expr: Option<Expression>,
283+
pub row_expr: Option<Expression>,
283284
pub colspan: u16,
284285
pub rowspan: u16,
285286
pub item: LayoutItem,
286287
}
287288

288289
impl GridLayoutElement {
289-
pub fn col_or_row_and_span(&self, orientation: Orientation) -> (u16, u16) {
290+
pub fn span(&self, orientation: Orientation) -> u16 {
290291
match orientation {
291-
Orientation::Horizontal => (self.col, self.colspan),
292-
Orientation::Vertical => (self.row, self.rowspan),
292+
Orientation::Horizontal => self.colspan,
293+
Orientation::Vertical => self.rowspan,
293294
}
294295
}
295296
}

internal/compiler/llr/expression.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,10 @@ impl<T> TypeResolutionContext for EvaluationContext<'_, T> {
730730
&self.compilation_unit.sub_components[sub_component.sub_components[*i].ty];
731731
}
732732

733-
sub_component.items[*item_index].ty.lookup_property(prop_name).unwrap()
733+
sub_component.items[*item_index]
734+
.ty
735+
.lookup_property(prop_name)
736+
.unwrap_or_else(|| panic!("property not found: {}", prop_name))
734737
}
735738
PropertyReference::InParent { level, parent_reference } => {
736739
let mut ctx = self;

internal/compiler/llr/lower_expression.rs

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,13 @@ fn compute_layout_info(
597597
crate::layout::Layout::GridLayout(layout) => {
598598
let (padding, spacing) = generate_layout_padding_and_spacing(&layout.geometry, o, ctx);
599599
let cells = grid_layout_cell_data(layout, o, ctx);
600+
let orientation_literal = llr_Expression::EnumerationValue(EnumerationValue {
601+
value: o as _,
602+
enumeration: crate::typeregister::BUILTIN.with(|b| b.enums.Orientation.clone()),
603+
});
600604
llr_Expression::ExtraBuiltinFunctionCall {
601605
function: "grid_layout_info".into(),
602-
arguments: vec![cells, spacing, padding],
606+
arguments: vec![cells, spacing, padding, orientation_literal],
603607
return_ty: crate::typeregister::layout_info_type().into(),
604608
}
605609
}
@@ -643,6 +647,10 @@ fn solve_layout(
643647
let (padding, spacing) = generate_layout_padding_and_spacing(&layout.geometry, o, ctx);
644648
let cells = grid_layout_cell_data(layout, o, ctx);
645649
let size = layout_geometry_size(&layout.geometry.rect, o, ctx);
650+
let orientation_expr = llr_Expression::EnumerationValue(EnumerationValue {
651+
value: o as _,
652+
enumeration: crate::typeregister::BUILTIN.with(|b| b.enums.Orientation.clone()),
653+
});
646654
if let (Some(button_roles), Orientation::Horizontal) = (&layout.dialog_button_roles, o)
647655
{
648656
let cells_ty = cells.ty(ctx);
@@ -669,37 +677,43 @@ fn solve_layout(
669677
},
670678
llr_Expression::ExtraBuiltinFunctionCall {
671679
function: "solve_grid_layout".into(),
672-
arguments: vec![make_struct(
673-
"GridLayoutData",
674-
[
675-
("size", Type::Float32, size),
676-
("spacing", Type::Float32, spacing),
677-
("padding", padding.ty(ctx), padding),
678-
(
679-
"cells",
680-
cells_ty.clone(),
681-
llr_Expression::ReadLocalVariable {
682-
name: "cells".into(),
683-
ty: cells_ty,
684-
},
685-
),
686-
],
687-
)],
680+
arguments: vec![
681+
make_struct(
682+
"GridLayoutData",
683+
[
684+
("size", Type::Float32, size),
685+
("spacing", Type::Float32, spacing),
686+
("padding", padding.ty(ctx), padding),
687+
(
688+
"cells",
689+
cells_ty.clone(),
690+
llr_Expression::ReadLocalVariable {
691+
name: "cells".into(),
692+
ty: cells_ty,
693+
},
694+
),
695+
],
696+
),
697+
orientation_expr,
698+
],
688699
return_ty: Type::LayoutCache,
689700
},
690701
])
691702
} else {
692703
llr_Expression::ExtraBuiltinFunctionCall {
693704
function: "solve_grid_layout".into(),
694-
arguments: vec![make_struct(
695-
"GridLayoutData",
696-
[
697-
("size", Type::Float32, size),
698-
("spacing", Type::Float32, spacing),
699-
("padding", padding.ty(ctx), padding),
700-
("cells", cells.ty(ctx), cells),
701-
],
702-
)],
705+
arguments: vec![
706+
make_struct(
707+
"GridLayoutData",
708+
[
709+
("size", Type::Float32, size),
710+
("spacing", Type::Float32, spacing),
711+
("padding", padding.ty(ctx), padding),
712+
("cells", cells.ty(ctx), cells),
713+
],
714+
),
715+
orientation_expr,
716+
],
703717
return_ty: Type::LayoutCache,
704718
}
705719
}
@@ -846,15 +860,33 @@ fn grid_layout_cell_data(
846860
.elems
847861
.iter()
848862
.map(|c| {
849-
let (col_or_row, span) = c.col_or_row_and_span(orientation);
863+
let span = c.span(orientation);
850864
let layout_info =
851865
get_layout_info(&c.item.element, ctx, &c.item.constraints, orientation);
852866

867+
let mut lower_expr_or_auto = |expr: &Option<crate::expression_tree::Expression>| {
868+
expr.as_ref().map_or_else(
869+
|| llr_Expression::NumberLiteral(u16::MAX.into()), // MAX means "auto", see to_layout_data()
870+
|e| lower_expression(e, ctx),
871+
)
872+
};
873+
let row_expr = lower_expr_or_auto(&c.row_expr);
874+
let col_expr = lower_expr_or_auto(&c.col_expr);
875+
853876
make_struct(
854877
"GridLayoutCellData",
855878
[
856879
("constraint", crate::typeregister::layout_info_type().into(), layout_info),
857-
("col_or_row", Type::Int32, llr_Expression::NumberLiteral(col_or_row as _)),
880+
("new_row", Type::Bool, llr_Expression::BoolLiteral(c.new_row)),
881+
(
882+
"col_or_row",
883+
Type::Int32,
884+
match orientation {
885+
Orientation::Horizontal => col_expr,
886+
Orientation::Vertical => row_expr.clone(),
887+
},
888+
),
889+
("row", Type::Int32, row_expr),
858890
("span", Type::Int32, llr_Expression::NumberLiteral(span as _)),
859891
],
860892
)
@@ -867,6 +899,7 @@ fn grid_layout_cell_data(
867899
pub(super) fn grid_layout_cell_data_ty() -> Type {
868900
Type::Struct(Rc::new(Struct {
869901
fields: IntoIterator::into_iter([
902+
(SmolStr::new_static("new_row"), Type::Bool),
870903
(SmolStr::new_static("col_or_row"), Type::Int32),
871904
(SmolStr::new_static("span"), Type::Int32),
872905
(SmolStr::new_static("constraint"), crate::typeregister::layout_info_type().into()),

0 commit comments

Comments
 (0)