This will allow later to be able to operate on the binding despite the
element is borrowed.
Since the Binding itself is in a RefCell, the analysis don't need to
be anymore.
To do this change, a small change in the binding_analysis logic was required
which means that we will now detect binding loop if a binding was causing
two binding loop. (before, only one binding loop was detected)
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.
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.
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.
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.
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.
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
We need to maintain the order of declaration and the sub-trees
of children need to be emitted before continuing with the parent.
This fixes the tab widget in the galler.y
There's a check that verifies that the relative item indices match, between what
the item tree building code in the generator sees and the generate_item_indices pass.
The counting of the relative indices was incorrect with regards to the sub-trees.
By accident the tree was still depth-first instead of level-order. This implementation works better,
by placing the root element of sub-components as
parents and the children into the children space later.
There's still more work to do to clean it up and make work with more complex scenarios.
(1) ... when the root element is a sub-component itself (the initialy child offset is not 1)
(2) when children themselves are sub-components, then they may occupy more entries in the item tree
Don't put them in a fake expression.
This simplifies a bit the expression handling, and will make
possible to fix analysis that needs a vew into the aliases
this implies that we need to make sure the property are initialized in
order so that constant properties that depends on other constant properties
are correctly computed
We need to embed resources in wasm builds. Unfortunately we can't detect
that we're called by say wasm-pack and "TARGET"/"HOST" only works inside
build.rs. So instead, to keep things simple, this change always embeds
the image resources when targeting Rust.
The `SIXTYFPS_EMBED_RESOURCES` environment variable can be used to
override this anywhere for any language.
Fixes#130
The objective is to have a bunch of .60 files with annotations inside
and the test harness picks them up and runs them through the Rust and
C++ frontend.
The LoweredItem and LoweredComponent contained, in essence, the same
information as the Element and Component in object_tree. Since the
moving declarations pass moved everything to the root element and the
LoweredPropertyDeclarations have been removed as well, this is the last
step.