Here are “widgets” from Faust’s point of view (from any Faust generated C++ file).
if (type == "hgroup") {
REAL_UI(ui_interface)->openHorizontalBox(it.label.c_str());
} else if (type == "vgroup") {
REAL_UI(ui_interface)->openVerticalBox(it.label.c_str());
} else if (type == "tgroup") {
REAL_UI(ui_interface)->openTabBox(it.label.c_str());
} else if (type == "vslider") {
REAL_UI(ui_interface)->addVerticalSlider(it.label.c_str(), REAL_ADR(index), init, min, max, step);
} else if (type == "hslider") {
REAL_UI(ui_interface)->addHorizontalSlider(it.label.c_str(), REAL_ADR(index), init, min, max, step);
} else if (type == "checkbox") {
REAL_UI(ui_interface)->addCheckButton(it.label.c_str(), REAL_ADR(index));
} else if (type == "soundfile") {
REAL_UI(ui_interface)->addSoundfile(it.label.c_str(), it.url.c_str(), SOUNDFILE_ADR(index));
} else if (type == "hbargraph") {
REAL_UI(ui_interface)->addHorizontalBargraph(it.label.c_str(), REAL_ADR(index), min, max);
} else if (type == "vbargraph") {
REAL_UI(ui_interface)->addVerticalBargraph(it.label.c_str(), REAL_ADR(index), min, max);
} else if (type == "nentry") {
REAL_UI(ui_interface)->addNumEntry(it.label.c_str(), REAL_ADR(index), init, min, max, step);
} else if (type == "button") {
REAL_UI(ui_interface)->addButton(it.label.c_str(), REAL_ADR(index));
} else if (type == "close") {
REAL_UI(ui_interface)->closeBox();
}
and here are the ones PGM supports:
[foleys_AutoOrientationSlider.h]
[foleys_FileBrowserDialog.cpp]
[foleys_FileBrowserDialog.h]
[foleys_MagicLevelMeter.cpp]
[foleys_MagicLevelMeter.h]
[foleys_MagicPlotComponent.cpp]
[foleys_MagicPlotComponent.h]
[foleys_MidiLearnComponent.cpp]
[foleys_MidiLearnComponent.h]
[foleys_XYDragComponent.cpp]
[foleys_XYDragComponent.h]
Also containers are described here:
We’re going to need to come up with a new class that is similar to the Faust JUCE “uiVUMeter” class implementation but compatible with PGM as well. It can act like an input-only slider as far as connecting to a signal.
/**
* \brief Intern class for VU-meter
* \details There is no JUCE widgets for VU-meter, so its fully designed in this class.
*/
class uiVUMeter : public uiComponent, public juce::SettableTooltipClient, public juce::Timer
{
private:
FAUSTFLOAT fLevel; // Current level of the VU-meter.
FAUSTFLOAT fMin, fMax; // Linear range of the VU-meter.
FAUSTFLOAT fScaleMin, fScaleMax; // Range in dB if needed.
bool fDB; // True if it's a dB VU-meter, false otherwise.
VUMeterType fStyle;
juce::String fUnit;
juce::Label fLabel; // Name of the VU-meter.
bool isNameDisplayed()
{
return (!(getName().startsWith("0x")) && getName().isNotEmpty());
}
/** Give the right coordinates and size to the text of Label depending on the VU-meter style */
void setLabelPos()
{
if (fStyle == VVUMeter) {
// -22 on the height because of the text box.
fLabel.setBounds((getWidth()-50)/2, getHeight()-22, 50, 20);
} else if (fStyle == HVUMeter) {
isNameDisplayed() ? fLabel.setBounds(63, (getHeight()-20)/2, 50, 20)
: fLabel.setBounds(3, (getHeight()-20)/2, 50, 20);
} else if (fStyle == NumDisplay) {
fLabel.setBounds((getWidth()-kNumDisplayWidth)/2,
(getHeight()-kNumDisplayHeight/2)/2,
kNumDisplayWidth,
kNumDisplayHeight/2);
}
}
/** Contain all the initialization need for our Label */
void setupLabel(juce::String tooltip)
{
setLabelPos();
fLabel.setEditable(false, false, false);
fLabel.setJustificationType(juce::Justification::centred);
fLabel.setText(juce::String((int)*fZone) + " " + fUnit, juce::dontSendNotification);
fLabel.setTooltip(tooltip);
addAndMakeVisible(fLabel);
}
/**
* \brief Generic method to draw an horizontal VU-meter.
* \details Draw the background of the bargraph, and the TextBox box, without taking
* care of the actual level of the VU-meter
* \see drawHBargraphDB
* \see drawHBargraphLin
*
* \param g JUCE graphics context, used to draw components or images.
* \param width Width of the VU-meter widget.
* \param height Height of the VU-meter widget.
* \param level Current level that needs to be displayed.
* \param dB True if it's a db level, false otherwise.
*/
void drawHBargraph(juce::Graphics& g, int width, int height)
{
float x;
float y = (float)(getHeight()-height)/2;
if (isNameDisplayed()) {
x = 120;
width -= x;
// VUMeter Name
g.setColour(juce::Colours::black);
g.drawText(getName(), 0, y, 60, height, juce::Justification::centredRight);
} else {
x = 60;
width -= x;
}
// VUMeter Background
g.setColour(juce::Colours::lightgrey);
g.fillRect(x, y, (float)width, (float)height);
g.setColour(juce::Colours::black);
g.fillRect(x+1.0f, y+1.0f, (float)width-2, (float)height-2);
// Label Window
g.setColour(juce::Colours::darkgrey);
g.fillRect((int)x-58, (getHeight()-22)/2, 52, 22);
g.setColour(juce::Colours::green.withAlpha(0.8f));
g.fillRect((int)x-57, (getHeight()-20)/2, 50, 20);
// Call the appropriate drawing method for the level.
fDB ? drawHBargraphDB (g, y, height) : drawHBargraphLin(g, x, y, width, height);
}
/**
* Method in charge of drawing the level of a horizontal dB VU-meter.
*
* \param g JUCE graphics context, used to draw components or images.
* \param y y coordinate of the VU-meter.
* \param height Height of the VU-meter.
* \param level Current level of the VU-meter, in dB.
*/
void drawHBargraphDB(juce::Graphics& g, int y, int height)
{
// Drawing Scale
g.setFont(9.0f);
g.setColour(juce::Colours::green);
for (int i = -10; i > fMin; i -= 10) {
paintScale(g, i);
}
for (int i = -6; i < fMax; i += 3) {
paintScale(g, i);
}
int alpha = 200;
FAUSTFLOAT dblevel = dB2Scale(fLevel);
// We need to test here every color changing levels, to avoid to mix colors because of the alpha,
// and so to start the new color rectangle at the end of the previous one.
// Drawing from the minimal range to the current level, or -10dB.
g.setColour(juce::Colour((juce::uint8)40, (juce::uint8)160, (juce::uint8)40, (juce::uint8)alpha));
g.fillRect(dB2x(fMin), y+1.0f, juce::jmin(dB2x(fLevel)-dB2x(fMin), dB2x(-10)-dB2x(fMin)), (float)height-2);
// Drawing from -10dB to the current level, or -6dB.
if (dblevel > dB2Scale(-10)) {
g.setColour(juce::Colour((juce::uint8)160, (juce::uint8)220, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(dB2x(-10), y+1.0f, juce::jmin(dB2x(fLevel)-dB2x(-10), dB2x(-6)-dB2x(-10)), (float)height-2);
}
// Drawing from -6dB to the current level, or -3dB.
if (dblevel > dB2Scale(-6)) {
g.setColour(juce::Colour((juce::uint8)220, (juce::uint8)220, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(dB2x(-6), y+1.0f, juce::jmin(dB2x(fLevel)-dB2x(-6), dB2x(-3)-dB2x(-6)), (float)height-2);
}
// Drawing from -3dB to the current level, or 0dB.
if (dblevel > dB2Scale(-3)) {
g.setColour(juce::Colour((juce::uint8)240, (juce::uint8)160, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(dB2x(-3), y+1.0f, juce::jmin(dB2x(fLevel)-dB2x(-3), dB2x(0)-dB2x(-3)), (float)height-2);
}
// Drawing from 0dB to the current level, or the max range.
if (dblevel > dB2Scale(0)) {
g.setColour(juce::Colour((juce::uint8)240, (juce::uint8)0, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(dB2x(0), y+1.0f, juce::jmin(dB2x(fLevel)-dB2x(0), dB2x(fMax)-dB2x(0)), (float)height-2);
}
}
/**
* Method in charge of drawing the level of a horizontal linear VU-meter.
*
* \param g JUCE graphics context, used to draw components or images.
* \param x x coordinate of the VU-meter.
* \param y y coordinate of the VU-meter.
* \param height Height of the VU-meter.
* \param width Width of the VU-meter.
* \param level Current level of the VU-meter, in linear logic.
*/
void drawHBargraphLin(juce::Graphics& g, int x, int y, int width, int height)
{
int alpha = 200;
juce::Colour c = juce::Colour((juce::uint8)255, (juce::uint8)165, (juce::uint8)0, (juce::uint8)alpha);
// Drawing from the minimal range to the current level, or 20% of the VU-meter
g.setColour(c.brighter());
g.fillRect(x+1.0f, y+1.0f, juce::jmin<float>(fLevel*(width-2), 0.2f*(width-2)), (float)height-2);
// Drawing from 20% of the VU-meter to the current level, or 90% of the VU-meter
if (fLevel > 0.2f) {
g.setColour(c);
g.fillRect(x+1.0f + 0.2f*(width-2), y+1.0f, juce::jmin<float>((fLevel-0.2f) * (width-2), (0.9f-0.2f) * (width-2)), (float)height-2);
}
// Drawing from 90% of the VU-meter to the current level, or the maximal range of the VU-meter
if (fLevel > 0.9f) {
g.setColour(c.darker());
g.fillRect(x+1.0f + 0.9f*(width-2), y+1.0f, juce::jmin<float>((fLevel-0.9f) * (width-2), (1.0f-0.9f) * (width-2)), (float)height-2);
}
}
/**
* \brief Generic method to draw a vertical VU-meter.
* \details Draw the background of the bargraph, and the TextBox box, without taking
* care of the actual level of the VU-meter
* \see drawHBargraphDB
* \see drawHBargraphLin
*
* \param g JUCE graphics context, used to draw components or images.
* \param width Width of the VU-meter widget.
* \param height Height of the VU-meter widget.
* \param level Current level that needs to be displayed.
* \param dB True if it's a db level, false otherwise.
*/
void drawVBargraph(juce::Graphics& g, int width, int height)
{
float x = (float)(getWidth()-width)/2;
float y;
if (isNameDisplayed()) {
y = (float)getHeight()-height+15;
height -= 40;
// VUMeter Name
g.setColour(juce::Colours::black);
g.drawText(getName(), getLocalBounds(), juce::Justification::centredTop);
} else {
y = (float)getHeight()-height;
height -= 25;
}
// VUMeter Background
g.setColour(juce::Colours::lightgrey);
g.fillRect(x, y, (float)width, (float)height);
g.setColour(juce::Colours::black);
g.fillRect(x+1.0f, y+1.0f, (float)width-2, (float)height-2);
// Label window
g.setColour(juce::Colours::darkgrey);
g.fillRect(juce::jmax((getWidth()-50)/2, 0), getHeight()-23, juce::jmin(getWidth(), 50), 22);
g.setColour(juce::Colours::green.withAlpha(0.8f));
g.fillRect(juce::jmax((getWidth()-48)/2, 1), getHeight()-22, juce::jmin(getWidth()-2, 48), 20);
fDB ? drawVBargraphDB (g, x, width) : drawVBargraphLin(g, x, width);
}
/**
* Method in charge of drawing the level of a vertical dB VU-meter.
*
* \param g JUCE graphics context, used to draw components or images.
* \param x x coordinate of the VU-meter.
* \param width Width of the VU-meter.
* \param level Current level of the VU-meter, in dB.
*/
void drawVBargraphDB(juce::Graphics& g, int x, int width)
{
// Drawing Scale
g.setFont(9.0f);
g.setColour(juce::Colours::green);
for (int i = -10; i > fMin; i -= 10) {
paintScale(g, i);
}
for (int i = -6; i < fMax; i += 3) {
paintScale(g, i);
}
int alpha = 200;
FAUSTFLOAT dblevel = dB2Scale(fLevel);
// We need to test here every color changing levels, to avoid to mix colors because of the alpha,
// and so to start the new color rectangle at the end of the previous one.
// Drawing from the minimal range to the current level, or -10dB.
g.setColour(juce::Colour((juce::uint8)40, (juce::uint8)160, (juce::uint8)40, (juce::uint8)alpha));
g.fillRect(x+1.0f, juce::jmax(dB2y(fLevel), dB2y(-10)), (float)width-2, dB2y(fMin)-juce::jmax(dB2y(fLevel), dB2y(-10)));
// Drawing from -10dB to the current level, or -6dB.
if (dblevel > dB2Scale(-10)) {
g.setColour(juce::Colour((juce::uint8)160, (juce::uint8)220, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(x+1.0f, juce::jmax(dB2y(fLevel), dB2y(-6)), (float)width-2, dB2y(-10)-juce::jmax(dB2y(fLevel), dB2y(-6)));
}
// Drawing from -6dB to the current level, or -3dB.
if (dblevel > dB2Scale(-6)) {
g.setColour(juce::Colour((juce::uint8)220, (juce::uint8)220, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(x+1.0f, juce::jmax(dB2y(fLevel), dB2y(-3)), (float)width-2, dB2y(-6)-juce::jmax(dB2y(fLevel), dB2y(-3)));
}
// Drawing from -3dB to the current level, or 0dB.
if (dblevel > dB2Scale(-3)) {
g.setColour(juce::Colour((juce::uint8)240, (juce::uint8)160, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(x+1.0f, juce::jmax(dB2y(fLevel), dB2y(0)), (float)width-2, dB2y(-3)-juce::jmax(dB2y(fLevel), dB2y(0)));
}
// Drawing from 0dB to the current level, or the maximum range.
if (dblevel > dB2Scale(0)) {
g.setColour(juce::Colour((juce::uint8)240, (juce::uint8)0, (juce::uint8)20, (juce::uint8)alpha));
g.fillRect(x+1.0f, juce::jmax(dB2y(fLevel), dB2y(fMax)), (float)width-2, dB2y(0)-juce::jmax(dB2y(fLevel), dB2y(fMax)));
}
}
/**
* Method in charge of drawing the level of a vertical linear VU-meter.
*
* \param g JUCE graphics context, used to draw components or images.
* \param x x coordinate of the VU-meter.
* \param width Width of the VU-meter.
* \param level Current level of the VU-meter, in linear logic.
*/
void drawVBargraphLin(juce::Graphics& g, int x, int width)
{
int alpha = 200;
juce::Colour c = juce::Colour((juce::uint8)255, (juce::uint8)165, (juce::uint8)0, (juce::uint8)alpha);
// Drawing from the minimal range to the current level, or 20% of the VU-meter.
g.setColour(c.brighter());
g.fillRect(x+1.0f, juce::jmax(lin2y(fLevel), lin2y(0.2)), (float)width-2, lin2y(fMin)-juce::jmax(lin2y(fLevel), lin2y(0.2)));
// Drawing from 20% of the VU-meter to the current level, or 90% of the VU-meter.
if (fLevel > 0.2f) {
g.setColour(c);
g.fillRect(x+1.0f, juce::jmax(lin2y(fLevel), lin2y(0.9)), (float)width-2, lin2y(0.2)-juce::jmax(lin2y(fLevel), lin2y(0.9)));
}
// Drawing from 90% of the VU-meter to the current level, or the maximum range.
if (fLevel > 0.9f) {
g.setColour(c.darker());
g.fillRect(x+1.0f, juce::jmax(lin2y(fLevel), lin2y(fMax)), (float)width-2, lin2y(0.9)-juce::jmax(lin2y(fLevel), lin2y(fMax)));
}
}
/**
* Method in charge of drawing the LED VU-meter, dB or not.
*
* \param g JUCE graphics context, used to draw components or images.
* \param width Width of the LED.
* \param height Height of the LED.
* \param level Current level of the VU-meter, dB or not.
*/
void drawLed(juce::Graphics& g, int width, int height)
{
float x = (float)(getWidth() - width)/2;
float y = (float)(getHeight() - height)/2;
g.setColour(juce::Colours::black);
g.fillEllipse(x, y, width, height);
if (fDB) {
int alpha = 200;
FAUSTFLOAT dblevel = dB2Scale(fLevel);
// Adjust the color depending on the current level
g.setColour(juce::Colour((juce::uint8)40, (juce::uint8)160, (juce::uint8)40, (juce::uint8)alpha));
if (dblevel > dB2Scale(-10)) {
g.setColour(juce::Colour((juce::uint8)160, (juce::uint8)220, (juce::uint8)20, (juce::uint8)alpha));
}
if (dblevel > dB2Scale(-6)) {
g.setColour(juce::Colour((juce::uint8)220, (juce::uint8)220, (juce::uint8)20, (juce::uint8)alpha));
}
if (dblevel > dB2Scale(-3)) {
g.setColour(juce::Colour((juce::uint8)240, (juce::uint8)160, (juce::uint8)20, (juce::uint8)alpha));
}
if (dblevel > dB2Scale(0)) {
g.setColour(juce::Colour((juce::uint8)240, (juce::uint8)0, (juce::uint8)20, (juce::uint8)alpha));
}
g.fillEllipse(x+1, y+1, width-2, height-2);
} else {
// The alpha depend on the level, from 0 to 1
g.setColour(juce::Colours::red.withAlpha((float)fLevel));
g.fillEllipse(x+1, y+1, width-2, height-2);
}
}
/**
* Method in charge of drawing the Numerical Display VU-meter, dB or not.
*
* \param g JUCE graphics context, used to draw components or images.
* \param width Width of the Numerical Display.
* \param height Height of the Numerical Display.
* \param level Current level of the VU-meter.
*/
void drawNumDisplay(juce::Graphics& g, int width, int height)
{
// Centering it
int x = (getWidth()-width) / 2;
int y = (getHeight()-height) / 2;
// Draw box.
g.setColour(juce::Colours::darkgrey);
g.fillRect(x, y, width, height);
g.setColour(juce::Colours::green.withAlpha(0.8f));
g.fillRect(x+1, y+1, width-2, height-2);
// Text is handled by the setLabelPos() function
}