Fix preferred size of the Window with a layout

A few problem:
 - the horizontal and vertical property were swapped
 - The implementation of the "preferred_xxx" property was not materialized properly
   because the `bindings` were borrowed in the materialize_fake_properties pass
 - Since the Window has a stretch factor of 0., the preferred size of the inner layout
   was not taken into account when merging the LayoutInfo.  I believe taking the
   maximum preferred size is the right solution when merging them.
This commit is contained in:
Olivier Goffart 2021-06-18 13:45:27 +02:00
parent 0a3ec534ae
commit a0bea36e43
5 changed files with 74 additions and 42 deletions

View file

@ -321,22 +321,11 @@ using cbindgen_private::sixtyfps_solve_path_layout;
inline LayoutInfo LayoutInfo::merge(const LayoutInfo &other) const
{
// Note: This "logic" is duplicated from LayoutInfo::merge in layout.rs.
const auto merge_preferred_size = [](float left_stretch, float left_size, float right_stretch,
float right_size) -> float {
if (left_stretch < right_stretch) {
return left_size;
} else if (left_stretch > right_stretch) {
return right_size;
} else {
return (left_size + right_size) / 2.;
}
};
return LayoutInfo { std::max(min, other.min),
std::min(max, other.max),
std::max(min_percent, other.min_percent),
std::min(max_percent, other.max_percent),
merge_preferred_size(stretch, preferred,
other.stretch, other.preferred),
std::max(preferred, other.preferred),
std::min(stretch, other.stretch) };
}

View file

@ -146,18 +146,18 @@ fn gen_layout_info_prop(elem: &ElementRc) {
"layoutinfo_h",
crate::layout::layout_info_type(),
);
elem.borrow_mut().layout_info_prop = Some((li_v.clone(), li_h.clone()));
elem.borrow_mut().layout_info_prop = Some((li_h.clone(), li_v.clone()));
let mut expr_h = implicit_layout_info_call(elem, Orientation::Horizontal);
let mut expr_v = implicit_layout_info_call(elem, Orientation::Vertical);
for child_info in child_infos {
expr_v = Expression::BinaryExpression {
lhs: Box::new(std::mem::take(&mut expr_v)),
expr_h = Expression::BinaryExpression {
lhs: Box::new(std::mem::take(&mut expr_h)),
rhs: Box::new(Expression::PropertyReference(child_info.0)),
op: '+',
};
expr_h = Expression::BinaryExpression {
lhs: Box::new(std::mem::take(&mut expr_h)),
expr_v = Expression::BinaryExpression {
lhs: Box::new(std::mem::take(&mut expr_v)),
rhs: Box::new(Expression::PropertyReference(child_info.1)),
op: '+',
};

View file

@ -20,17 +20,17 @@ use std::collections::HashMap;
use std::rc::Rc;
pub fn materialize_fake_properties(component: &Rc<Component>) {
let mut to_initialize = std::collections::HashSet::new();
recurse_elem_including_sub_components_no_borrow(component, &(), &mut |elem, _| {
visit_all_named_references_in_element(elem, |nr| {
let elem = nr.element();
let must_initialize = {
let mut elem = elem.borrow_mut();
let elem = &mut *elem;
maybe_materialize(&mut elem.property_declarations, &elem.base_type, nr.name())
if maybe_materialize(&mut elem.property_declarations, &elem.base_type, nr.name())
&& !elem.bindings.contains_key(nr.name())
};
if must_initialize {
initialize(elem, nr.name());
{
to_initialize.insert(nr.clone());
}
});
let mut elem = elem.borrow_mut();
@ -38,7 +38,14 @@ pub fn materialize_fake_properties(component: &Rc<Component>) {
for prop in elem.bindings.keys() {
maybe_materialize(&mut elem.property_declarations, &elem.base_type, prop);
}
})
});
for nr in to_initialize {
let elem = nr.element();
if !elem.borrow().bindings.contains_key(nr.name()) {
initialize(elem, nr.name())
}
}
}
fn maybe_materialize(

View file

@ -59,27 +59,12 @@ impl Default for LayoutInfo {
impl LayoutInfo {
// Note: This "logic" is duplicated in the cpp generator's generated code for merging layout infos.
pub fn merge(&self, other: &LayoutInfo) -> Self {
let merge_preferred_size = |left_stretch, left_size, right_stretch, right_size| {
if left_stretch < right_stretch {
left_size
} else if left_stretch > right_stretch {
right_size
} else {
(left_size + right_size) / 2.
}
};
Self {
min: self.min.max(other.min),
max: self.max.min(other.max),
min_percent: self.min_percent.max(other.min_percent),
max_percent: self.max_percent.min(other.max_percent),
preferred: merge_preferred_size(
self.stretch,
self.preferred,
other.stretch,
other.preferred,
),
preferred: self.preferred.max(other.preferred),
stretch: self.stretch.min(other.stretch),
}
}

View file

@ -0,0 +1,51 @@
/* LICENSE BEGIN
This file is part of the SixtyFPS Project -- https://sixtyfps.io
Copyright (c) 2020 Olivier Goffart <olivier.goffart@sixtyfps.io>
Copyright (c) 2020 Simon Hausmann <simon.hausmann@sixtyfps.io>
SPDX-License-Identifier: GPL-3.0-only
This file is also available under commercial licensing terms.
Please contact info@sixtyfps.io for more information.
LICENSE END */
TestCase := Window {
VerticalLayout {
padding: 10px;
spacing: 27px;
Rectangle {
background: blue;
preferred-width: 25phx;
preferred-height: 500phx;
horizontal-stretch: 0;
vertical-stretch: 0;
}
Rectangle {
background: green;
// implicit: horizontal-stretch: 1
}
}
property w <=> root.preferred-width;
property <bool> test: root.preferred_height == 500phx + 20px + 27px && root.preferred_width == 25phx + 20px;
}
/*
```cpp
auto handle = TestCase::create();
const TestCase &instance = *handle;
assert(instance.get_test());
```
```rust
let instance = TestCase::new();
assert!(instance.get_test());
```
```js
var instance = new sixtyfps.TestCase();
assert(instance.test);
```
*/