GetDunne Wiki

Notes from the desk of Shane Dunne, software development consultant

User Tools

Site Tools


the_plugin_editor

This is an old revision of the document!


The VanillaJuce plugin Editor (GUI)

The VanillaJuceAudioProcessorEditor class defined in PluginEditor.h is very simple, and little changed from what was automatically generated by the Projucer:

class VanillaJuceAudioProcessorEditor
    : public AudioProcessorEditor
    , public ChangeListener
{
public:
    VanillaJuceAudioProcessorEditor (VanillaJuceAudioProcessor&);
    ~VanillaJuceAudioProcessorEditor();
 
    void paint (Graphics&) override;
    void resized() override;
 
    virtual void changeListenerCallback(ChangeBroadcaster* source);
 
private:
    VanillaJuceAudioProcessor& processor;
    GuiTabs guiTabs;
 
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VanillaJuceAudioProcessorEditor)
};

The editor GUI is entirely built from JUCE Component-class objects. It consists of a single GuiTabs object (the guiTabs member variable above), which itself owns and contains all the other Components. As you'll see below, all of my Gui… classes take a SynthSound* pointer as a constructor argument, and implement a void notify() member function which gets called whenever any parameter is changed. Here is the entire PluginEditor.cpp file (except for the #include lines at the top):

VanillaJuceAudioProcessorEditor::VanillaJuceAudioProcessorEditor (VanillaJuceAudioProcessor& p)
    : AudioProcessorEditor (&p)
    , processor (p)
    , guiTabs(p.getSound())
{
    setSize (600, 400);
    addAndMakeVisible(&guiTabs);
    p.addChangeListener(this);
}
 
VanillaJuceAudioProcessorEditor::~VanillaJuceAudioProcessorEditor()
{
    processor.removeChangeListener(this);
}
 
void VanillaJuceAudioProcessorEditor::paint (Graphics& g)
{
    ignoreUnused(g);
}
 
void VanillaJuceAudioProcessorEditor::resized()
{
    guiTabs.setBounds(0, 0, proportionOfWidth(1.0000f), proportionOfHeight(1.0000f));
}
 
void VanillaJuceAudioProcessorEditor::changeListenerCallback(ChangeBroadcaster* source)
{
    ignoreUnused(source);
    guiTabs.notify();
}

The constructor calls the processor's getSound() function to get a pointer to the one shared SynthSound object, which it passes to the constructor for guiTabs. It also sets the GUI window size, calls juce::Component::addAndMakeVisible() to add the tabs object as a child Component of the editor, and registers the editor as a change-listener to the processor. The destructor unregisters it.

The resized() function sets the bounds of the guiTabs object so it completely fills the editor window. As a consequence, the paint() function has nothing to do, because the tabs object will render the entire window contents.

The editor inherits from juce::ChangeListener, hence it implements changeListenerCallback(), which simply calls guiTabs.notify() (which will propagate the change notification to all of its child GUI components.)

The GuiTabs object

The GuiTabs class is a container for a juce::TabbedComponent object, and three “tab” Components which are added to it:

class GuiTabs  : public Component
{
public:
    GuiTabs (SynthSound* pSynthSound);
    ~GuiTabs();
 
    void paint (Graphics& g) override;
    void resized() override;
 
    void notify();
 
private:
    ScopedPointer<TabbedComponent> tabbedComponent;
    GuiMainTab* pMainTab;
    GuiOscTab* pOscTab;
    GuiEgTab* pAmpEgTab;
 
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GuiTabs)
};
 
GuiTabs::GuiTabs (SynthSound* pSynthSound)
{
    addAndMakeVisible (tabbedComponent = new TabbedComponent (TabbedButtonBar::TabsAtTop));
    tabbedComponent->setTabBarDepth (32);
    tabbedComponent->addTab(TRANS("Main"), Colours::lightgrey, pMainTab = new GuiMainTab(pSynthSound), true);
    tabbedComponent->addTab (TRANS("Osc"), Colours::lightgrey, pOscTab = new GuiOscTab(pSynthSound), true);
    tabbedComponent->addTab(TRANS("AmpEG"), Colours::lightgrey, pAmpEgTab = new GuiEgTab(pSynthSound), true);
    tabbedComponent->setCurrentTabIndex(0);
}
 
GuiTabs::~GuiTabs()
{
    // tabbedComponent will take care of deleting our tab objects
    tabbedComponent = nullptr;
}
 
//==============================================================================
void GuiTabs::paint (Graphics& g)
{
    g.fillAll (Colour (0xff323e44));
}
 
void GuiTabs::resized()
{
    tabbedComponent->setBounds (0, 0, proportionOfWidth (1.0000f), proportionOfHeight (1.0000f));
}
 
void GuiTabs::notify()
{
    pMainTab->notify();
    pOscTab->notify();
    pAmpEgTab->notify();
}

The constructor creates the tabbedComponent object and calls addAndMakeVisible() on it, sets the depth of the tabs bar to 32 pixels, creates the three tab objects and calls tabbedComponent→addTab, and sets the first (zeroth) tab to be the initially-selected one.

the_plugin_editor.1504118108.txt.gz · Last modified: 2017/08/30 18:35 by shane