Stl.Browsers.Template¶
Stl.Browsers.Template is a parameterized browser component for building tag-filtered, scrollable sound and preset selection UIs. Products instantiate it once per browser with a unique namespace, then override a small set of required hooks to wire in their data model and UI widgets.
Why This Exists¶
A sound browser combines tag filtering, scrollable lists, preview playback, cancel/restore state, keyboard navigation, and display rendering. These concerns are common to every instrument that has a browser, but the data each browser operates on is product-specific. The template pattern separates the mechanism (filtering, scrolling, selection) from the data (what to show, how to render it, how to load it).
Key Concepts¶
Template Declaration¶
node MyBrowser from Stl.Browsers.Template(#name#, #max_items#, #num_tags#, #num_entries#):
// implement required hooks
end node| Parameter | Purpose |
|---|---|
#name# |
Namespace prefix for all generated identifiers |
#max_items# |
Total item capacity |
#num_tags# |
Number of tag filter buttons |
#num_entries# |
Number of visible rows in the browser list |
Multiple independent browsers coexist without collision because all generated identifiers are prefixed with #name#.
Required Hooks¶
| Hook | Purpose |
|---|---|
hooks.get_tag_state(idx) -> state |
Return ON/OFF state of tag button |
hooks.set_tag_state(idx, state) |
Write ON/OFF state back to tag button |
hooks.load_item(selected_item) |
Load and activate the item |
hooks.play_preview(selected_item, key_modifiers) |
Start audio preview |
hooks.stop_preview() |
Stop any active preview |
ui.hooks.render_entry(entry_idx, state, visible, item_id) |
Redraw visible entry row |
ui.hooks.render_tag(tag_idx, tag_available) |
Redraw tag button |
Tag Filtering¶
Tags are stored as bitmasks. Each item has a mask assigned to #name#.masks[item]. The current active filter is #name#.currentFilter. Items that match the filter are appended to #name#.current_items[].
#name#.availableTags tracks which tags have at least one matching item under the current filter — render_tag receives this as tag_available so products can visually disable tags that would produce no results.
Filter update flow:
User clicks tag button
→ tag state toggled
→ #name#.reingest_tags()
→ ui.tag_btns_to_filter() // reads widget states into currentFilter
→ process_filter() // rebuilds current_items[], updates availableTags
→ render_tag() for each tag
→ scrollbar.update()
→ ui.entry_list.refresh()
→ render_entry() for each visible rowFallback (Cancel) State¶
The browser maintains a cancel-restore point:
#name#.set_fallback(generic_id, item, filter_mask)
#name#.current_to_fallback() // saves current filter + focused_item
#name#.fallback() // restores saved filter + item
#name#.fallback_sound_only() // restores item only, not filterfallback is called by the abort/cancel button callback. On double-click, current_to_fallback() saves the state as a new restore point.
Scrollbar Companion¶
Every browser requires a companion scrollbar node instantiated with the same namespace:
node MyBrowserScrollbar from Stl.Scrollbar.Template(
#name#.scrollbar,
scroll.orient.VERTICAL,
MyBrowser.ScrollXY,
MyBrowser.ScrollThumb,
NUM_ENTRIES,
#name#.current_items.count
):The scrollbar automatically wires a response function that calls #name#.ui.entry_list.refresh() whenever its position changes.
Navigation¶
taskfunc #name#.jump_focus_by(offset) // -1 or +1, wired to prev/next buttons
function #name#.jump_to_focused_item(item) // scroll to bring item into viewConfiguration Options¶
#name#.options.defaultFilter // Mask: tags active when no filter applied
#name#.options.alwaysAvailableTags // Mask: tags always shown regardless of filter
#name#.options.auto_preview := TRUE // single-click plays preview
#name#.options.auto_load := TRUE // single-click loads itemSylvan Phrases Example¶
Sylvan's Phr.Browser uses 18 visible entries and 22 tags. In cb FirstLoad it initializes all sound masks (phr.browser.init_family_tags()). render_entry sets button text, BPM label, and font/color states. render_tag sets button image frames and enable/disable state.
hooks.load_item triggers sound assignment, refreshes the key mapping, calls purge.execute(), and redraws the main UI. hooks.play_preview fires a preview note event.
Connections to Other Parts of IVLS¶
The browser's hooks.load_item typically triggers purge (to load the newly assigned sound's groups) and ui-routines (to update the main UI state). stl-play-event is ultimately triggered when a browser item is previewed or played.
Patterns and Caveats¶
- Initialize all masks (
Maskobjects for each item) incb FirstLoad, notcb Init. Atcb Inittime the NKA data may not yet be loaded. - The browser uses
uicb.Bindto wire entry and tag buttons. All binding must happen incb Initafter widget IDs are resolved. auto_preview = TRUEandauto_load = TRUEcan conflict in instruments where selecting a sound and loading it are separate actions. Set them based on whether single-click should have immediate effect.- The
fallbackstate is reset togeneric_id = -1on browser open. Callset_fallbackorcurrent_to_fallbackexplicitly to establish a restore point before any user interaction.
Related¶
- stl-play-event — triggered when browser item is previewed or loaded
- purge — load_item typically calls purge.execute() to make the new sound's groups resident