We can now set all the properties exposed to the
business logic of a UI we are previewing.
Simple properties only so far, everything else falls
back to JSON data.
Next step is to add more sophisticated UI to actually
edit more complex data like arrays more graphically.
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.
```
warning: passing a unit value to a function
--> internal/interpreter/eval.rs:752:29
|
752 | / ... item_rc_
753 | | ... .downcast::<corelib::items::ContextMenu>()
754 | | ... .unwrap()
755 | | ... .activated
756 | | ... .call(&(args[0].clone().try_into().unwrap(),))
757 | | ... .into()
| |_________________________________^
|
```
Activate, contrary to the other callback, doesn't return a value.
So write the Value::Void directly instead of using the fact that
`().into()` a value would produce Value::Void.
The code is more fragile as it will stop working if `activated` changed
return type and it no longer look consistant with the other call, but
let's make clippy happy anyway
Because we set the viewport-width several time to different value during
the layouting of the ListView, it will cause this property to always be
dirty. In particular, this causes permanent restart of the fluent's
scrollbar animation on the size of the handle, causing continous
repaints.
Introduce two new properties for string in .slint:
- .is-empty: Checks if a string is empty.
- .character-count: Retrieves the number of grapheme clusters
https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
These additions enhance functionality and improve convenience when working with string properties.
Added image-default-formats with all the format supported by image by
default, and enable that feature by default.
Also put that feature in compat-1-2 for compatibility with user that
have used image 0.24 with enabled features.
Make a new compat-1-10 feature that does not enable default format by
default
ChangeLog: upgraded image crate to 0.25, added a new cargo feature
to enable all image formats. (that feature is enabled by default with
compat-1-2, added compat-1-10 to disable it
Fixes https://github.com/slint-ui/slint/issues/7251
The instance passed to close_popup() was not the same as the one passed
to show_popup(), when called from another component. Fix this by
determining the instance in BuiltinFunction::ClosePopupWindow the same
way as in BuiltinFunction::ShowPopupWindow.
This issue was covered by popup_window_close.slint's JS test, but it was
commented out because we used to run the Node.js tests on Linux with Qt,
for which the popup testing doesn't work the same way in terms of
synthetic event delivery.
We decided to change that, also in light of the nodejs binaries we
upload to the NPM registry also being built without Qt support anyway.
This permits running additional popup window tests, providing test
coverage for the interpreter, some of which needed light syntax fixes.
Co-authored-by: Olivier Goffart <olivier.goffart@slint.dev>
Fixes#7318
Only the interpreter is implemented so far
MacOs won't work yet because we don't disable the default winit menubar
The viewer don't support removing the MenuBar yet
Based on API review, PlatformBuilder becomes BackendSelector with
a slightly smaller API surface but more options, such as selecting
Metal or Vulkan rendering.
Fix test for #6984
Since global can cross-reference eachother, the Global storage need to
be a Rc of all global, and not a clone of the HashMap.
We need to hold it in a RefCell as new global are added during
initialization.
But then we can't take reference to the Rc<Global> anymore, so we need
to take a clone of it, meaning that the InstanceRef cannot be Copy.
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
```
Popups are stored in a HashMap and are assigned an ID so popup.close(); closes the correct popup and so a single PopupWindow cannot be opened multiple times
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 allows us to cheaply copy the langtype::Type values which
contain such a type. The runtime impact is small and barely noticable
but a sampling profiler shows a clear reduction in samples pointing
at langtype.rs, roughly reducing that from ~8.6% inclusive cost
down to 6.6% inclusive cost.
Furthermore, this allows us to share/intern common types.
Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 1.089 s ± 0.026 s [User: 0.771 s, System: 0.216 s]
Range (min … max): 1.046 s … 1.130 s 10 runs
allocations: 3152149
```
After:
```
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
```
Copying potentially thousands of properties for no reason is something
that can be easily optimized away to save a bit of time:
Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 1.108 s ± 0.015 s [User: 0.792 s, System: 0.231 s]
Range (min … max): 1.085 s … 1.133 s 10 runs
```
After:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 1.082 s ± 0.019 s [User: 0.773 s, System: 0.214 s]
Range (min … max): 1.054 s … 1.117 s 10 runs
```
This removes a lot of temporary allocations, note e.g. how this
was called once per component previously yet the data contained
in the map was always the same!
Before:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 636.2 ms ± 20.0 ms [User: 563.4 ms, System: 71.8 ms]
Range (min … max): 615.2 ms … 657.9 ms 10 runs
allocations: 3371939
```
After:
```
Benchmark 1: ./target/release/slint-viewer ../slint-perf/app.slint
Time (mean ± σ): 600.6 ms ± 2.9 ms [User: 522.0 ms, System: 74.4 ms]
Range (min … max): 596.3 ms … 605.2 ms 10 runs
allocations: 2917930
```