Skip to content

Add dynamic_combobox: a combobox with a runtime-populated item list#171

Open
bltzr wants to merge 3 commits into
celtera:mainfrom
bltzr:feature/dynamic-combobox
Open

Add dynamic_combobox: a combobox with a runtime-populated item list#171
bltzr wants to merge 3 commits into
celtera:mainfrom
bltzr:feature/dynamic-combobox

Conversation

@bltzr

@bltzr bltzr commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

PR (avendish): dynamic_combobox — runtime-populated combobox port

Branch: feature/dynamic-combobox (off main)
Files: 2 new headers, 79 lines, no changes to existing code.

What

A combobox port whose item list is discovered by the processor at run time,
rather than fixed at compile time by range():

struct ins {
  halp::folder_port<"Folder"> folder;
  halp::dynamic_combobox<"File"> file;   // items filled at runtime
} inputs;

void operator()(int) {
  if (folder_changed && inputs.file.update_items)
    inputs.file.update_items(list_of_names);   // any thread
  // inputs.file.value is the selected index
}
  • halp/dynamic_combobox.hpp — the port: int value, a static fallback
    range() (single "-" item), and
    std::function<void(std::vector<std::string>)> update_items.
  • avnd/concepts/dynamic_items.hppavnd::dynamic_items_parameter<T>, so a
    binding can detect these ports.

Backwards compatibility

The design is additive and opt-in. Bindings that don't know the concept never
fill update_items; the port then renders as a plain combobox from the static
fallback range(). Existing objects and existing bindings are untouched — no
API, ABI or behaviour change.

Host side

The score binding that consumes this is a companion PR on ossia/score
(feature/dynamic-combobox): Process::ComboBox gains
setAlternatives() + alternativesChanged, the widgets rebuild live, and the
executor injects update_items (thread-marshalled). Other bindings can adopt
it incrementally or ignore it.

Motivation

Folder-backed pickers: the score-avnd-flucoma / Granola work needs a sound
whose choices are the files currently in a working folder. Also useful for OSC
address lists, dataset point ids, device names, preset names — any choice set
known only at run time. Full design notes in dynamic-combobox-proposal.md.

Open questions for review

  1. Callback injection (chosen here) vs. reusing the processor→UI message bus.
  2. Value semantics when the list changes: clamp index (host PR does this) vs.
    match by string.

Host binding

ossia/score#2110 consumes this port: Process::ComboBox gains a runtime setAlternatives() + alternativesChanged, the inspector/canvas widgets rebuild live, and the avnd executor injects update_items. This avendish PR should land first. No real object depends on it yet — it was verified with a throwaway test object.

A combobox port whose choices are discovered by the processor at run time
(e.g. the files in a folder, OSC addresses, dataset ids) rather than being
fixed at compile time.

The port carries an update_items callback that supporting bindings inject and
that the object invokes — from any thread — whenever its list changes.
Bindings without support leave the callback empty and render a plain combobox
from the static fallback range(), so the feature is fully backwards-compatible:
no API, ABI or behaviour change for existing objects.

avnd::dynamic_items_parameter lets a binding detect such ports.

Co-authored-by: Pia Baltazar <pia@baltazar.studio>
@bltzr

bltzr commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Host-side consumer: ossia/score#2110 (adds the Process::ComboBox runtime API + executor injection). This avendish PR is the standalone piece and can be reviewed independently.

@bltzr

bltzr commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Closing for now — no real object consumes this port yet (Granola, the intended user, went with a custom picker), so I don't want to add to your review queue. The work stays on my fork branch bltzr:feature/dynamic-combobox; I'll reopen once a concrete object adopts halp::dynamic_combobox. Thanks!

@bltzr bltzr closed this Jul 13, 2026
@bltzr

bltzr commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Leaving this as a reference rather than an active review request. A working example of the port in use: DynComboTest in score-avnd-flucoma — lists a folder's audio files in a halp::dynamic_combobox that repopulates live as the folder changes, verified in the running app (host binding: ossia/score#2110).

For our actual case — Granola's sound picker — we ended up doing it manually with a custom widget instead, so nothing here is blocking us. But if you think a runtime-populated combobox would be useful to others in the codebase, happy to revive and polish both PRs (this port + the score binding).

A combobox whose items are the files of a sibling folder/path port, listed by
the host at edit time and refreshed when the folder changes — populated at
document load, without execution. Complements dynamic_combobox (which is
pushed by the running object); this pulls from a folder in the UI, matching
how file pickers actually need to behave in an editor.

Co-authored-by: Pia Baltazar <pia@baltazar.studio>
@bltzr

bltzr commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

related to ossia/score#2110 so reopening along with the latter

@bltzr bltzr reopened this Jul 13, 2026
Chains of processes that write then read conventionally-named files rely on
default values; keep the initially selected file name as a parameter so it
stays selected even while the file does not exist yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDQaHG5FbEyH9D8VsjEyXe
@bltzr

bltzr commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Added an init file-name template parameter (folder_combobox<name, folder_port, extensions, init>): chains of processes that write then read conventionally-named files keep working with defaults — the init stays selected even while the file does not exist yet, and is picked up once written.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant