Missing feature:
- conversion between Value and enums
- conversion from value to Model
- Compatibility with the testing framework (get the `VRc<ItemTreeTable>` from an instance)
Previously to see errors or debug info using debug(...) required the output panel of a speperate IDE or for Slintpad to open the browser developer tools.
This PR adds a dedicated panel to the live-preview. Log messages include a link back to the source file and line number for fast finding where the message was generated. Syntax errors also now show in the logs.
By default the panel is minimised and logs will clear themselves on UI recompile. The last log message does show as a preview on the minimised bar meaning in many cases you never need to open the panel.
---------
Co-authored-by: Tobias Hunger <tobias.hunger@slint.dev>
When converting a ModelRc<T> to a Value, the resulting model did not
implement set_row_data and therefore would not allow changing the model
from the code.
By adding a `TryFrom` bound, we can make sure set_row_data is
implemented.
This is technically a breaking change to add this bound, but most type
that implement From for value also implement TryFrom<Value>
These conversion function were added in
20443ec0df for Slint 1.9
ChangeLog: interpreter: The `From<ModelRc> for slint_interpreter::Value` now gives a model that supports `set_row_data`.
Once upon a time, the enum were written in snake case in the .rs file,
but since ac4f3e97ad, they are written
in camel case, and the strenum crate takes care of moving that to kebab
case, which match our normalization, so there is no need to normalize
more.
The de-normalization was actually broken since
63f7533dc9 which changed a
denormalization into a normalization for the TryFrom<Value>
`__1` is a valid identifier, which we normalized to
`--1`, which is invalid.
This changes the nromalization function to leave a `_` in the first position.
This means the event loop spawning goes through the backend, which will permit for state from the Backend struct to be available when spinning the event loop even when spawning it merely.
Extract the `from_json` and `to_json` code from the viewer into the `interpreter`.
Extend the `from_json` and `to_json` a bit. Add some simple tests while at it.
Based on API review, PlatformBuilder becomes BackendSelector with
a slightly smaller API surface but more options, such as selecting
Metal or Vulkan rendering.
SmolStr has an Arc internally for large strings. This allows
cheap copies of large strings, but we lose that ability
when we convert the SmolStr to a &str and then reconstruct a
SmolStr from that slice.
I was hoping for some larger gains here, considering the impact
of this code change, but it only removes ~50k allocations,
while the impact on the runtime is not noticeable at all.
Still, I believe this is the right thing to do.
Before:
```
allocations: 2338981
Time (mean ± σ): 988.3 ms ± 17.9 ms [User: 690.2 ms, System: 206.4 ms]
Range (min … max): 956.4 ms … 1016.3 ms 10 runs
```
After:
```
allocations: 2287723
Time (mean ± σ): 989.8 ms ± 23.2 ms [User: 699.2 ms, System: 197.6 ms]
Range (min … max): 945.3 ms … 1021.4 ms 10 runs
```
This is rarely used, but using Rc here like elsewhere allows us to
elide a few unneccessary memory allocations when copying such types.
The speed impact is not measurable though. With heaptrack I see that
we get rid of the last ~7600 allocations in my benchmark when cloning
Type.
This makes copying such types much cheaper and will allow us to
intern common struct types in the future too. This further
drops the sample cost for langtype.rs from ~6.6% down to 4.0%.
We are now also able to share/intern common struct types.
Before:
```
Time (mean ± σ): 1.073 s ± 0.021 s [User: 0.759 s, System: 0.215 s]
Range (min … max): 1.034 s … 1.105 s 10 runs
allocations: 3074261
```
After:
```
Time (mean ± σ): 1.034 s ± 0.026 s [User: 0.733 s, System: 0.201 s]
Range (min … max): 1.000 s … 1.078 s 10 runs
allocations: 2917476
```
This removes a lot of allocations and speeds up the compiler step
a bit. Sadly, this patch is very invasive as it touches a lot of
files. That said, each individual hunk is pretty trivial.
For a non-trivial real-world example, the impact is significant,
we get rid of ~29% of all allocations and improve the runtime by
about 4.8% (measured until the viewer loop would start).
Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 664.2 ms ± 6.7 ms [User: 589.2 ms, System: 74.0 ms]
Range (min … max): 659.0 ms … 682.4 ms 10 runs
allocations: 4886888
temporary allocations: 857508
```
After:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 639.5 ms ± 17.8 ms [User: 556.9 ms, System: 76.2 ms]
Range (min … max): 621.4 ms … 666.5 ms 10 runs
allocations: 3544318
temporary allocations: 495685
```
In rust, use f32 instead of f64 for arithmetic comparison.
In the interpreter, use approx_eq
The test is failling in nightly because of precision change in `log`.
By using f32, it actually should work
Also Revert "Disable builds with nightly Rust temporarily"
This reverts commit 4afc3a2e84.
Fixes#5722
Use this snapshot to keep a unoptimized typeloader around, so that the preview
does not need to do another parsing run.
Move the document cache in the preview over to use the snapshot.