gfx/containers.h
A list, a set of tabs, and a progress bar.
#include <sonore/gfx/containers.h>- 3types
- Guides: The native editor
On this page
Design notes
Why these three
A ListBox is what a preset browser IS -- also a sample list, a modulation slot list, a device list. A synth with an oscillator page, a filter page and an envelope page is the ordinary shape of an instrument editor, and that is a TabbedComponent. And loading a sample library is the one thing a plugin does that takes long enough to need a progress bar.
The list is virtual
ListBox draws rows on demand from a model rather than owning a component per row. A preset browser with four thousand presets would otherwise build four thousand components, each with bounds and a paint method, to show twelve of them. Everything below the fold costs nothing here.
Types 3
class ListBox : public Widget
A scrolling list of rows, drawn on demand.
The model is two callbacks rather than a subclass to implement: how many rows there are, and how to draw one. A plugin's list is usually a vector it already has, and making it inherit from something to show that vector is ceremony with no payoff.
class TabbedComponent : public Widget
Pages behind a row of tabs.
The pages are NOT owned, for the same reason nothing else here owns its content: a plugin builds its panels as members and a container that took them over would decide a lifetime the plugin already decided.
class ProgressBar : public Widget
A bar that fills.
Reads its value through a pointer rather than being told, because the thing making progress is usually on another thread -- a sample library loading -- and a bar that had to be pushed at would need that thread to know about the UI. A value another thread writes is a std::atomic<double>; a plain double is for one written on the message thread, which is the thread that reads it.