mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
Layouting: Take in account explicit constraints when generating layout info base on content (#6306)
Fixes #6285 ChangeLog: Fixed geometry constraints when they are partially infered from the content, and partially infered from the explicit constraints
This commit is contained in:
parent
25ae55b5dd
commit
53e79000a4
4 changed files with 131 additions and 5 deletions
|
@ -6,9 +6,6 @@ import { AppText } from "./controls/generic.slint";
|
|||
import { AboutSlint } from "std-widgets.slint";
|
||||
|
||||
component AboutFelgo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 5px;
|
||||
|
||||
|
@ -81,7 +78,7 @@ export component AboutBox {
|
|||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AboutSlint {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
|
|
@ -179,10 +179,10 @@ impl LayoutConstraints {
|
|||
apply_size_constraint("height", s, enclosing, depth, &mut constraints.max_height);
|
||||
});
|
||||
find_binding(element, "width", |s, enclosing, depth| {
|
||||
constraints.fixed_width = true;
|
||||
if s.expression.ty() == Type::Percent {
|
||||
apply_size_constraint("width", s, enclosing, depth, &mut constraints.min_width);
|
||||
} else {
|
||||
constraints.fixed_width = true;
|
||||
apply_size_constraint("width", s, enclosing, depth, &mut constraints.min_width);
|
||||
apply_size_constraint("width", s, enclosing, depth, &mut constraints.max_width);
|
||||
}
|
||||
|
|
|
@ -216,6 +216,14 @@ fn gen_layout_info_prop(elem: &ElementRc, diag: &mut BuildDiagnostics) {
|
|||
let mut expr_h = implicit_layout_info_call(elem, Orientation::Horizontal);
|
||||
let mut expr_v = implicit_layout_info_call(elem, Orientation::Vertical);
|
||||
|
||||
let explicit_constraints = LayoutConstraints::new(elem, diag);
|
||||
if !explicit_constraints.fixed_width {
|
||||
merge_explicit_constraints(&mut expr_h, &explicit_constraints, Orientation::Horizontal);
|
||||
}
|
||||
if !explicit_constraints.fixed_height {
|
||||
merge_explicit_constraints(&mut expr_v, &explicit_constraints, Orientation::Vertical);
|
||||
}
|
||||
|
||||
for child_info in child_infos {
|
||||
if let Some(h) = child_info.0 {
|
||||
expr_h = Expression::BinaryExpression {
|
||||
|
@ -239,6 +247,55 @@ fn gen_layout_info_prop(elem: &ElementRc, diag: &mut BuildDiagnostics) {
|
|||
li_h.element().borrow_mut().bindings.insert(li_h.name().into(), expr_h.into());
|
||||
}
|
||||
|
||||
fn merge_explicit_constraints(
|
||||
expr: &mut Expression,
|
||||
constraints: &LayoutConstraints,
|
||||
orientation: Orientation,
|
||||
) {
|
||||
if constraints.has_explicit_restrictions(orientation) {
|
||||
static COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
|
||||
let unique_name =
|
||||
format!("layout_info_{}", COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed));
|
||||
let ty = expr.ty();
|
||||
let store = Expression::StoreLocalVariable {
|
||||
name: unique_name.clone(),
|
||||
value: Box::new(std::mem::take(expr)),
|
||||
};
|
||||
let Type::Struct { fields, .. } = &ty else { unreachable!() };
|
||||
let mut values = fields
|
||||
.keys()
|
||||
.map(|p| {
|
||||
(
|
||||
p.clone(),
|
||||
Expression::StructFieldAccess {
|
||||
base: Expression::ReadLocalVariable {
|
||||
name: unique_name.clone(),
|
||||
ty: ty.clone(),
|
||||
}
|
||||
.into(),
|
||||
name: p.clone(),
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
for (nr, s) in constraints.for_each_restrictions(orientation) {
|
||||
let e = nr
|
||||
.element()
|
||||
.borrow()
|
||||
.bindings
|
||||
.get(nr.name())
|
||||
.expect("constraint must have binding")
|
||||
.borrow()
|
||||
.expression
|
||||
.clone();
|
||||
debug_assert!(!matches!(e, Expression::Invalid));
|
||||
values.insert(s.into(), e);
|
||||
}
|
||||
*expr = Expression::CodeBlock([store, Expression::Struct { ty, values }].into());
|
||||
}
|
||||
}
|
||||
|
||||
fn explicit_layout_info(e: &ElementRc, orientation: Orientation) -> Expression {
|
||||
let mut values = HashMap::new();
|
||||
let (size, orient) = match orientation {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||
|
||||
|
||||
component C1 {
|
||||
Rectangle {
|
||||
min-width: 200px;
|
||||
min-height: 300px;
|
||||
inner := Rectangle {}
|
||||
}
|
||||
}
|
||||
component C2 {
|
||||
Rectangle {
|
||||
min-width: 200px;
|
||||
min-height: 300px;
|
||||
inner := Rectangle { width: 100%; }
|
||||
}
|
||||
}
|
||||
|
||||
component FillParent {
|
||||
preferred-height: 100%;
|
||||
preferred-width: 100%;
|
||||
min-height: l.min-height;
|
||||
min-width: l.min-width;
|
||||
|
||||
l := VerticalLayout {
|
||||
Text {}
|
||||
}
|
||||
}
|
||||
|
||||
export component Bug6315 {
|
||||
r := Rectangle {
|
||||
width: self.preferred-width;
|
||||
r2 := Rectangle {
|
||||
preferred-width: 100px;
|
||||
Rectangle {
|
||||
preferred-width: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (
|
||||
"\{r.width / 1px}, " +
|
||||
"\{r2.width / 1px}, " +
|
||||
""
|
||||
);
|
||||
}
|
||||
out property <bool> ok: r.width == 100px && r2.width == 100px;
|
||||
}
|
||||
|
||||
|
||||
export component W inherits Window {
|
||||
|
||||
Rectangle {
|
||||
VerticalLayout {
|
||||
FillParent {
|
||||
min-height: self.preferred-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c1:= C1 {}
|
||||
c2:= C2 {}
|
||||
|
||||
bug-6315 := Bug6315 {}
|
||||
|
||||
|
||||
out property <bool> test: c1.min-height == 300px && c1.min-width == 200px
|
||||
&& c2.min-height == 300px && c2.min-width == 200px
|
||||
&& bug-6315.ok;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue