Control Hierarchy
All IGraphics controls derive from the IControl base class:
class IControl {
// Base class for all UI widgets
virtual void Draw ( IGraphics & g ) = 0 ; // Render the control
virtual void OnMouseDown ( float x , float y , const IMouseMod & mod );
virtual void OnMouseDrag ( float x , float y , float dX , float dY , const IMouseMod & mod );
// ... more event handlers
};
Controls are categorized into:
IVControls Vector/SVG-based controls
IBControls Bitmap-based controls
ISVGControls SVG image controls
Vector Controls (IVControls)
Vector controls use the IGraphics drawing API for scalable, styleable widgets.
IVKnobControl
A rotary knob with customizable appearance:
IVKnobControl ( const IRECT & bounds, int paramIdx,
const char * label = "" ,
const IVStyle & style = DEFAULT_STYLE,
bool valueIsEditable = false , bool valueInWidget = false ,
float a1 = - 135. f , float a2 = 135. f , float aAnchor = - 135. f ,
EDirection direction = EDirection ::Vertical,
double gearing = DEFAULT_GEARING, float trackSize = 2. f );
// Example usage
pGraphics -> AttachControl (
new IVKnobControl ( bounds . GetCentredInside ( 100 ), kParamGain, "Gain" ,
DEFAULT_STYLE, true )
);
a1, a2: Start and end angles in degrees (0° = up)
aAnchor: Anchor angle for bipolar knobs
gearing: Mouse sensitivity multiplier
valueIsEditable: Double-click for text entry
IVSliderControl
Vertical or horizontal slider:
IVSliderControl.h:319-322
IVSliderControl ( const IRECT & bounds, int paramIdx = kNoParameter,
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
bool valueIsEditable = false , EDirection dir = EDirection ::Vertical,
double gearing = DEFAULT_GEARING, float handleSize = 8. f ,
float trackSize = 2. f , bool handleInsideTrack = false );
// Vertical slider
pGraphics -> AttachControl (
new IVSliderControl (bounds, kParamCutoff, "Cutoff" , style, true ,
EDirection ::Vertical)
);
// Horizontal slider
pGraphics -> AttachControl (
new IVSliderControl (bounds, kParamPan, "Pan" , style, true ,
EDirection ::Horizontal)
);
Momentary button with click animation:
IVButtonControl ( const IRECT & bounds, IActionFunction aF = SplashClickActionFunc,
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
bool labelInButton = true , bool valueInButton = true ,
EVShape shape = EVShape ::Rectangle);
// Example with action function
pGraphics -> AttachControl ( new IVButtonControl (bounds,
[]( IControl * pCaller ) {
SplashClickActionFunc (pCaller); // Built-in splash animation
DBGMSG ( "Button clicked! \n " );
},
"Click Me" , style)
);
IVSwitchControl
Multi-state switch control:
IVSwitchControl ( const IRECT & bounds, int paramIdx = kNoParameter,
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
bool valueInButton = true );
// 4-state filter mode switch
pGraphics -> AttachControl (
new IVSwitchControl (bounds, kParamFilterMode, "Mode" , style)
);
IVToggleControl
Two-state toggle with custom on/off text:
IVToggleControl ( const IRECT & bounds, int paramIdx = kNoParameter,
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
const char * offText = "OFF" , const char * onText = "ON" );
pGraphics -> AttachControl (
new IVToggleControl (bounds, kParamBypass, "Bypass" , style, "OFF" , "ON" )
);
IVTabSwitchControl
Tab-based multi-switch:
IVTabSwitchControl ( const IRECT & bounds, int paramIdx = kNoParameter,
const std ::vector < const char *>& options = {},
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
EVShape shape = EVShape ::Rectangle,
EDirection direction = EDirection ::Horizontal);
pGraphics -> AttachControl ( new IVTabSwitchControl (
bounds, kParamWaveform,
{ "Sine" , "Triangle" , "Square" , "Saw" },
"Waveform" , style, EVShape ::EndsRounded, EDirection ::Horizontal)
);
Radio button group:
IVRadioButtonControl.h:211-212
IVRadioButtonControl ( const IRECT & bounds, int paramIdx = kNoParameter,
const std ::initializer_list < const char *>& options = {},
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
EVShape shape = EVShape ::Ellipse,
EDirection direction = EDirection ::Vertical,
float buttonSize = 10. f );
pGraphics -> AttachControl ( new IVRadioButtonControl (
bounds, kParamOscType,
{ "Sine" , "Square" , "Triangle" , "Saw" },
"Oscillator" , style, EVShape ::Ellipse, EDirection ::Vertical, 10. f )
);
IVXYPadControl
Two-dimensional XY pad for controlling two parameters:
IVXYPadControl ( const IRECT & bounds,
const std ::initializer_list < int >& params,
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
float handleRadius = 10. f , bool trackClipsHandle = true ,
bool drawCross = true );
pGraphics -> AttachControl ( new IVXYPadControl (
bounds, {kParamCutoff, kParamResonance}, "Filter" , style, 12. f )
);
IVRangeSliderControl
Dual-handle range slider:
IVRangeSliderControl.h:359
IVRangeSliderControl ( const IRECT & bounds,
const std ::initializer_list < int >& params,
const char * label = "" , const IVStyle & style = DEFAULT_STYLE,
EDirection dir = EDirection ::Vertical, bool onlyHandle = false ,
float handleSize = 8. f , float trackSize = 2. f );
pGraphics -> AttachControl ( new IVRangeSliderControl (
bounds, {kParamLowFreq, kParamHighFreq}, "Range" , style,
EDirection ::Horizontal, false , 8. f , 2. f )
);
Bitmap Controls (IBControls)
Bitmap controls use image files for their appearance.
IBKnobControl
Knob using multi-frame bitmap:
IBKnobControl ( const IRECT & bounds, const IBitmap & bitmap, int paramIdx,
EDirection direction = EDirection ::Vertical,
double gearing = DEFAULT_GEARING);
// Load 60-frame knob bitmap
const IBitmap knobBitmap = pGraphics -> LoadBitmap ( "knob.png" , 60 );
pGraphics -> AttachControl (
new IBKnobControl ( bounds . GetCentredInside ( 60 ), knobBitmap, kParamGain)
);
The bitmap should contain frames stacked vertically or horizontally. The frame count is specified when loading.
IBKnobRotaterControl
Knob that rotates a single image:
IBKnobRotaterControl.h:759-760
IBKnobRotaterControl ( const IRECT & bounds, const IBitmap & bitmap, int paramIdx);
const IBitmap pointer = pGraphics -> LoadBitmap ( "pointer.png" );
pGraphics -> AttachControl (
new IBKnobRotaterControl (bounds, pointer, kParamGain)
);
Button using multi-frame bitmap:
IBButtonControl.h:705-707
IBButtonControl ( const IRECT & bounds, const IBitmap & bitmap,
IActionFunction aF = DefaultClickActionFunc);
const IBitmap buttonBitmap = pGraphics -> LoadBitmap ( "button.png" , 2 ); // off/on
pGraphics -> AttachControl ( new IBButtonControl (bounds, buttonBitmap,
[]( IControl * pCaller ) {
// Button action
})
);
IBSwitchControl
Multi-state switch using bitmap:
IBSwitchControl ( const IRECT & bounds, const IBitmap & bitmap,
int paramIdx = kNoParameter);
const IBitmap switchBitmap = pGraphics -> LoadBitmap ( "switch.png" , 2 , true );
pGraphics -> AttachControl (
new IBSwitchControl (bounds, switchBitmap, kParamBypass)
);
IBSliderControl
Slider using handle and track bitmaps:
IBSliderControl.h:774-776
IBSliderControl ( const IRECT & bounds, const IBitmap & handleBitmap,
const IBitmap & trackBitmap = IBitmap (),
int paramIdx = kNoParameter, EDirection dir = EDirection ::Vertical,
double gearing = DEFAULT_GEARING);
const IBitmap handle = pGraphics -> LoadBitmap ( "slider_handle.png" );
const IBitmap track = pGraphics -> LoadBitmap ( "slider_track.png" );
pGraphics -> AttachControl (
new IBSliderControl (bounds, handle, track, kParamVolume, EDirection ::Vertical)
);
SVG Controls (ISVGControls)
Controls that use SVG vector images:
ISVGKnobControl
Rotating SVG knob:
ISVGKnobControl ( const IRECT & bounds, const ISVG & svg, int paramIdx = kNoParameter);
const ISVG knobSVG = pGraphics -> LoadSVG ( "knob.svg" );
pGraphics -> AttachControl (
new ISVGKnobControl ( bounds . GetCentredInside ( 80 ), knobSVG, kParamGain)
);
SVG button with on/off states:
ISVGButtonControl ( const IRECT & bounds, IActionFunction aF,
const ISVG & offImage, const ISVG & onImage);
// Or with color override:
ISVGButtonControl ( const IRECT & bounds, IActionFunction aF, const ISVG & image,
const std ::array < IColor, 4 > colors,
EColorReplacement colorReplacement = EColorReplacement ::Fill);
const ISVG icon = pGraphics -> LoadSVG ( "power.svg" );
pGraphics -> AttachControl ( new ISVGButtonControl (
bounds, []( IControl * p ) { /* action */ }, icon,
{COLOR_BLACK, COLOR_GREEN, COLOR_DARK_GRAY, COLOR_LIGHT_GRAY},
EColorReplacement ::Fill)
);
ISVGSliderControl
Slider using SVG handle and track:
ISVGSliderControl ( const IRECT & bounds, const ISVG & handleSvg,
const ISVG & trackSVG, int paramIdx = kNoParameter,
EDirection dir = EDirection ::Vertical,
double gearing = DEFAULT_GEARING);
const ISVG handle = pGraphics -> LoadSVG ( "handle.svg" );
const ISVG track = pGraphics -> LoadSVG ( "track.svg" );
pGraphics -> AttachControl (
new ISVGSliderControl (bounds, handle, track, kParamCutoff)
);
Visualization Controls
IVMeterControl
Level meter with optional peak hold:
IVMeterControl.h (from IControls.h)
IVMeterControl < N >( const IRECT & bounds, const char * label = "" ,
const IVStyle & style = DEFAULT_STYLE,
EDirection dir = EDirection ::Vertical,
const std ::initializer_list < const char *>& trackNames = {});
// Stereo meter
pGraphics -> AttachControl (
new IVMeterControl < 2 >(bounds, "Meter" , style, EDirection ::Vertical,
{ "L" , "R" }),
kCtrlTagMeter
);
// Send data from DSP
mMeterSender . ProcessBlock (outputs, nFrames, kCtrlTagMeter);
IVScopeControl
Oscilloscope display:
IVScopeControl.h (from IControls.h)
IVScopeControl < NChannels , BufferSize >( const IRECT & bounds,
const char * label = "" ,
const IVStyle & style = DEFAULT_STYLE);
const int kScopeBufferSize = 512 ;
pGraphics -> AttachControl (
new IVScopeControl < 2 , kScopeBufferSize >(bounds, "Scope" ,
style . WithColor (kBG, COLOR_BLACK). WithColor (kFG, COLOR_GREEN)),
kCtrlTagScope
);
// Send data from DSP
mScopeSender . ProcessBlock (outputs, nFrames, kCtrlTagScope);
IVKeyboardControl
MIDI keyboard widget:
IVKeyboardControl.h (from IControls.h)
IVKeyboardControl ( const IRECT & bounds, int minNote = 36 , int maxNote = 72 );
pGraphics -> AttachControl (
new IVKeyboardControl (bounds, 36 , 84 ) // C2 to C7
)-> SetActionFunction ([ this ]( IControl * pControl ) {
// Handle note on/off
});
IVSpectrumAnalyzerControl
Frequency spectrum analyzer:
IVSpectrumAnalyzerControl.h (from IControls.h)
IVSpectrumAnalyzerControl <>( const IRECT & bounds, const char * label = "" ,
const IVStyle & style = DEFAULT_STYLE);
pGraphics -> AttachControl (
new IVSpectrumAnalyzerControl <>(bounds, "Spectrum" , style),
kCtrlTagSpectrum
);
Styling Vector Controls
All IVControls support the IVStyle styling system:
const IVStyle style = DEFAULT_STYLE
. WithColor (kBG, COLOR_DARK_GRAY) // Background
. WithColor (kFG, COLOR_WHITE) // Foreground
. WithColor (kPR, COLOR_BLUE) // Pressed
. WithColor (kFR, COLOR_BLACK) // Frame
. WithColor (kHL, COLOR_LIGHT_GRAY) // Highlight
. WithColor (kSH, COLOR_BLACK) // Shadow
. WithRoundness ( 0.5 f ) // 0-1, corner radius
. WithFrameThickness ( 2. f ) // Frame line width
. WithShadowOffset ( 3. f ) // Shadow distance
. WithDrawFrame ( true ) // Enable frame
. WithDrawShadows ( true ) // Enable shadows
. WithEmboss ( true ) // Embossed look
. WithShowLabel ( true ) // Show label
. WithShowValue ( true ) // Show value
. WithWidgetFrac ( 0.8 f ) // Widget size fraction
. WithLabelText ( IText ( 14. f , COLOR_WHITE))
. WithValueText ( IText ( 12. f , COLOR_LIGHT_GRAY));
Text Controls
ITextControl
Static text label:
pGraphics -> AttachControl (
new ITextControl (bounds, "Label" , IText ( 16. f , COLOR_WHITE))
);
IEditableTextControl
Editable text field:
pGraphics -> AttachControl (
new IEditableTextControl (bounds, "Edit me" , IText ( 14. f ))
);
ICaptionControl
Parameter value display:
pGraphics -> AttachControl (
new ICaptionControl (bounds, kParamGain, IText ( 24. f ), COLOR_WHITE, false )
);
Container Controls
IVGroupControl
Visual grouping with frame:
IVGroupControl ( const IRECT & bounds, const char * label = "" ,
float labelOffset = 10. f , const IVStyle & style = DEFAULT_STYLE);
// Group by bounds
pGraphics -> AttachControl (
new IVGroupControl (bounds, "Oscillator" , 10. f , style)
);
// Or group by control group name
pGraphics -> AttachControl (
new IVGroupControl ( "Filter" , "filtercontrols" , 10. f , 30. f , 10. f , 10. f , style)
);
IVPanelControl
Simple styled panel:
IVPanelControl ( const IRECT & bounds, const char * label = "" ,
const IVStyle & style = ...);
pGraphics -> AttachControl (
new IVPanelControl (bounds, "" , style . WithColor (kFG, COLOR_MID_GRAY))
);
Next Steps
Custom Controls Build your own controls
Responsive UI Handle resizing and scaling
Getting Started Create your first UI
Drawing Backends Learn about NanoVG vs Skia