When we have
```
S1 := Rectangle {}
S2 := S1 {}
App := Window {
S2 {}
}
```
Then the right path to the rectangle is
offsetof(App, s2) + offsetof(S2, root) + offset(S1, rectangle)
The middle one was left out in C++, where it also probably doesn't matter
because the root is the first member (although it might not always remain that way).
In Rust the FieldOffset type generated won't allow for adding
together without the middle one.
Therefore visit_item() in the generator is changed to bring forward the sub-component
state when following the chain.
* For sub-components create a super-primitive struct with just its fields
and a new() function to create it. There's no init() function yet.
* Provide access to the root item of the sub-component
This just makes the most trivial example work:
```
SubComp := Rectangle {}
App := Window {
SubComp {
background: green;
}
}
```
Pass the sub-component as a parameter in enter_component(), as it's needed in the C++
implementation, it's readily available (no need to unwrap again) and Rust will need it, too.
In the tree builder's enter_component we registered the sub-component as a member
and also registered the member initializer
in the constructor.
However the call to `init()` to initialize the bindings was registered in `enter_component_children` for no good reason.
It's cleaner to do that all in one place.
For the following reduced test-case the order in how the dynamic nodes
in the item tree were generated (and dyn indices assigned) differed from
the way the visit_dynamic_children slots were generated:
```
Blah := Rectangle {
for x in 1: Text {
text: "Should be on the right";
}
}
MainWindow := Window {
width: 772px;
height: 504px;
Text {
if (false): TouchArea {
}
}
Blah {
x: 200px;
}
}
```
The item tree node was constructed using build_item_tree, which
basically assigned dyn index 0 to the "repater" for the touch area
and "1" to the one for the repeater inside the sub-component.
Afterwards we traversed the element tree - without descending into the
sub-components - to generate the fields and the dispatch in in the
dynamic visitor. Here a subtle order would result in a mismatch of
indices:
recurse_elem_level_order would end up visiting Text, Blah and then
Text's children, assigning the first dynamic index to Blah.
This is now fixed by merging the two iterations into one.
because we don't want the lowered state property to look like we set a property on it.
Also do the ensure_window before because it need to be done before to be assigned
the default color
Some code like this was generated:
`if (*self->checkbox_31.get_checked()).get()`
the remove_parentheses function removed a parentheses that it shouldn't have removed
Commit da169b0e3c surfaced the issue, which
existed earlier:
In such a scenarion the C++ struct has only one member (the sub-component) and it wasn't initialized,
because we never called visit_sub_component.
Fix the dialog test when not inlining, because it declared all these
xxx-clicked aliases and if we don't propagate their usage, they will be
optimized away
focus() is implemented by calling set_focus() on the window with the absolute item
index as a parameter. The
generate_item_indices pass generates local item indicies,
which need to made absolute.
Sadly there exists a gap in the item tree between the root element of a sub-component
and its children. Therefore each sub-component gets two members passed to the constructor,
the tree_index and tree_index_of_first_child.
The former is to be used when the local index is zero (indicates the root).
The latter is used as base for any children.
In a tree like this:
```
SubCompo := Rectangle { Image {} }
MainCompo := Window {
TouchArea {}
SubCompo {}
Text {
Path {}
}
}
```
The path element would have a local item index of 4, which is wrong. Right before the path
there would be the child(ren) of the sub-component, which
were not accounted for.
The variable in C++ sub-components is sometimes unused. We could try to lazily emit it, but
that requires more work and this is distracting :-). This silencing should hopefully also work for gcc.
This reverts commit fde3846392 because it
breaks the gcc build ("error: 'maybe_unused' attribute ignored
[-Werror=attributes]"). Will need a different solution that works for
clang (which warns about m_root_ being unused).
This reverts commit b4a2d0a902.
That was not the correct fix, because we need that for
aliases to global callbacks (these can't be actual two way binding
at runtime)
Calling init on sub-components with self_weak as argument only works after self_weak is
initialized, which happens in create(). So a new init() function for root components is called afterwards.
We never ended up passing the right index but always zero.
Fix by rewriting build_item_tree to be basically the same as build_array_helper,
with two differences:
(1) we maintain absolute and relative children offsets and parent indices
(2) When traversing over the children of an element there are two scenarios: either
the element is a sub-component, in which case we iterate through the children of the root element,
or we can use ElementRc's children directly