Commit 5fdc5ba
committed
ComboBox: reverse-lookup current-value writes into current-index
Implements Option A from #11970: a host write to current-value now
means "select the row with this value" — the widget finds it in the
model via array.index-of and moves current-index to match. A value
that isn't in the model resolves to no selection (current-index -1,
current-value ""), the same as setting current-index out of range —
and, unlike the successful case, logs a debug() message naming the
value, so a developer debugging an unexpectedly-cleared selection has
something to go on. A successful reverse lookup stays silent.
Uses index-of rather than find-index: ComboBox is the first built-in
widget with any dependency on the array-predicates machinery, and
index-of is the stable half of it (see the previous commit) — so this
carries no dependency on the still-experimental find-index/any/all
gate (#12777), unlike an inline find-index((value) => value ==
current-value) predicate would.
This supersedes the non-reverting interim behavior from 7dfcfdf,
which deliberately left an unmatched host write in place (with only a
debug() warning) to avoid disturbing existing `<=>` two-way bindings
while the real fix was blocked on iteration support. That blocker is
gone for this narrow case: index-of needs no general loop, only a
single-pass reverse lookup, so we no longer need the non-reverting
compromise. `<=>` bindings that round-trip an arbitrary, not-in-model
string through current-value will now see it replaced (with "" or the
first match) instead of preserved — this is intentional, matching the
issue's Option A design, not a regression.
RadioGroup is intentionally left untouched: its public API (declared
in builtins.slint) exposes current-value as `out` only and never
exposes current-index at all, so the only host-writable selection path
is `checked` on an individual RadioButton child, which already
correctly stays in sync with current-index/current-value (see
RadioButtonImplBase's `changed checked` handler) — there's no
writable-but-unreliable surface left for a reverse lookup to fix.
Known limitation, documented in combobox-base.slint and combobox.mdx:
the reverse lookup runs from `changed current-value`, which only fires
on an actual value transition. A write that doesn't change the
property — writing the value it already holds, or a value equal to a
later duplicate in `model` while an earlier duplicate should now be
selected per the "first match" contract — is a no-op. Slint has no
`.slint`-level hook for "run on every write regardless of value
equality" (the Rust-internal equivalent, BindingCallable::
intercept_set, isn't usable from widget source), so this can't be
closed without new core machinery; it equally affected the debug()-only
interim mitigation this replaces. Covered by two regression-documenting
assertions in tests/cases/widgets/combobox.slint so the behavior stays
intentional and visible rather than silently drifting.
changelog: ComboBox: writes to `current-value` from host code (Rust/C++/JS/Python) now update the selection via reverse lookup instead of being silently discarded. Fixes #11970 for ComboBox.1 parent 5ae0c1a commit 5fdc5ba
3 files changed
Lines changed: 72 additions & 14 deletions
File tree
- docs/astro/src/content/docs/reference/std-widgets/basic-widgets
- internal/compiler/widgets/common
- tests/cases/widgets
Lines changed: 10 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
49 | 55 | | |
50 | 56 | | |
51 | 57 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
84 | | - | |
85 | | - | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
86 | 89 | | |
87 | 90 | | |
88 | 91 | | |
89 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
90 | 97 | | |
91 | 98 | | |
92 | 99 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
256 | 256 | | |
257 | 257 | | |
258 | 258 | | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
263 | 262 | | |
264 | 263 | | |
265 | | - | |
266 | | - | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
267 | 312 | | |
268 | 313 | | |
269 | 314 | | |
0 commit comments