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>
This exposes FocusReason to .slint, and adds it as an argument to focus-event-changed callback on FocusScope to close#8387. It also adds two new callbacks, focus-gained and focus-lost, which are identical to focus-event-changed but are only invoked on focus gain or loss respectively.
In addition to this, it removes the FocusEventReason::AccessKit variant, replacing it with the mouse variant to hopefully make AccessKit more compatible with any Slint code that will use FocusEventReason.
Finally, I added two tests based on focus_change_event.slint, one for testing the FocusEventReason argument and another for testing the new callbacks.
close#8387
ChangeLog: Added `focus-gained` and `focus-lost` callback to FocusScope. Pass an `FocusReason` enum to the FocusScope callbacks
Closes#5992
Adds the enum FocusEventReason and makes it an argument for FocusEvent. This reason could eventually be exposed in Slint to solve #8387.
Using the focus reason tracking, I also added a select all on keyboard focus for TextInputs (except on macOS), which should close#5992.
ChangeLog: TextInput selects its content when focused with the keyboard on Windows and Linux
... by changing the resolution for the `WindowItem` to traverse the
item tree from the current item, instead of going to the window.
This doesn't quite fix#4298 because `rem` resolution is still missing.
That requires the built-in default font size function to be fixed as
well, which is non-trivial.
cc #4298
Conversion from negative float to unsigned is saturating to 0 in rust
and undefined behavior in C++, we should therefore handle the case
properly
Fixes#8222
You can not create this expression manually, but there
is a pass in the compiler that adds it to all set
properties in a compilation run.
All it does is basically associate an id with an expression,
so that we can then in a later step have the interpreter do
something with that information. Apart from that, it tries to
be as transparent as possible.
The LLR lowering removes that expression again, just so we can
be sure it does not end up in the generated live code.
This does some refactoring to allow builtin item functions to return a
value:
- builtin member functions are no longer BuiltinFunction, but they are
just normal NamedReference
- Move special case for them in the LLR/eval
Adds methods to change a `string`'s case to lowercase or uppercase.
They use Rust's `to_lowercase` and `to_uppercase` `String` methods.
ChangeLog: Added string.to-lowercase and string.to-uppercase
Closes#7860
Add two new float to string conversion methods that mimic
JavaScript's Number.toFixed() and Number.toPrecision().
They are implemented as no_mangle functions similar to the already
existing float to shared string conversion.
Closes#5822
```
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
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.
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
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 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
```
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
```
The struct held provides access to the design metrics of the font scaled
to the font pixel size used by the element.
ChangeLog: Slint Language: Added font-metrics property to `Text` and `TextInput`.
Closes#6047
When calling `popup.show()` the parent itemtree of the popup should be
the one from the parent in which the PopupWindow is declared in the
source, and not the one of the context in which the `popup.show()` code
appears.
Part of issue #6426.
This happens to fix the issue as presented there.
But there is another issue in which we still crash when trying to access
global from a popup who's parent has been deleted because the interpreter
needs access to the root item tree to access the globals
Because f64 has too much precision, so limit to f32 so that we don't
have extra precision we don't need and would be wrong as all our float
as in f32
(Also avoid double allocation in rust generated code)
- Make sure that in Rust and C++ we also truncate if the properties are
inlined
- Change the interpreter to truncate
This is a redo of commit f5d003d but truncate instead of round
fixes#5689