commit 28fc6635bc515680dc28916b9a11c69a444e56a7
parent 9d09b5e15b314eba3b96fdd70171e3f1ad1f0072
Author: falkTX <falktx@falktx.com>
Date: Mon, 9 Mar 2020 19:40:26 +0000
Add simple file handling example, WIP
Signed-off-by: falkTX <falktx@falktx.com>
Diffstat:
6 files changed, 783 insertions(+), 0 deletions(-)
diff --git a/examples/FileHandling/DistrhoPluginInfo.h b/examples/FileHandling/DistrhoPluginInfo.h
@@ -0,0 +1,47 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any purpose with
+ * or without fee is hereby granted, provided that the above copyright notice and this
+ * permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED
+#define DISTRHO_PLUGIN_INFO_H_INCLUDED
+
+#define DISTRHO_PLUGIN_BRAND "DISTRHO"
+#define DISTRHO_PLUGIN_NAME "FileHandling"
+#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/FileHandling"
+
+#define DISTRHO_PLUGIN_HAS_UI 1
+#define DISTRHO_PLUGIN_IS_RT_SAFE 1
+#define DISTRHO_PLUGIN_NUM_INPUTS 1
+#define DISTRHO_PLUGIN_NUM_OUTPUTS 1
+#define DISTRHO_PLUGIN_WANT_STATE 1
+#define DISTRHO_PLUGIN_WANT_STATEFILES 1
+#define DISTRHO_UI_USER_RESIZABLE 1
+#define DISTRHO_UI_USE_NANOVG 1
+
+enum Parameters {
+ kParameterFileSize1 = 0,
+ kParameterFileSize2,
+ kParameterFileSize3,
+ kParameterCount
+};
+
+enum States {
+ kStateFile1 = 0,
+ kStateFile2,
+ kStateFile3,
+ kStateCount
+};
+
+#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED
diff --git a/examples/FileHandling/FileHandlingPlugin.cpp b/examples/FileHandling/FileHandlingPlugin.cpp
@@ -0,0 +1,257 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any purpose with
+ * or without fee is hereby granted, provided that the above copyright notice and this
+ * permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "DistrhoPlugin.hpp"
+
+START_NAMESPACE_DISTRHO
+
+// -----------------------------------------------------------------------------------------------------------
+
+/**
+ Plugin to demonstrate File handling within DPF.
+ */
+class FileHandlingExamplePlugin : public Plugin
+{
+public:
+ FileHandlingExamplePlugin()
+ : Plugin(kParameterCount, 0, kStateCount)
+ {
+ std::memset(fParameters, 0, sizeof(fParameters));
+ }
+
+protected:
+ /* --------------------------------------------------------------------------------------------------------
+ * Information */
+
+ /**
+ Get the plugin label.
+ This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
+ */
+ const char* getLabel() const override
+ {
+ return "FileHandling";
+ }
+
+ /**
+ Get an extensive comment/description about the plugin.
+ */
+ const char* getDescription() const override
+ {
+ return "Plugin to demonstrate File handling.";
+ }
+
+ /**
+ Get the plugin author/maker.
+ */
+ const char* getMaker() const override
+ {
+ return "DISTRHO";
+ }
+
+ /**
+ Get the plugin homepage.
+ */
+ const char* getHomePage() const override
+ {
+ return "https://github.com/DISTRHO/DPF";
+ }
+
+ /**
+ Get the plugin license name (a single line of text).
+ For commercial plugins this should return some short copyright information.
+ */
+ const char* getLicense() const override
+ {
+ return "ISC";
+ }
+
+ /**
+ Get the plugin version, in hexadecimal.
+ */
+ uint32_t getVersion() const override
+ {
+ return d_version(0, 0, 0);
+ }
+
+ /**
+ Get the plugin unique Id.
+ This value is used by LADSPA, DSSI and VST plugin formats.
+ */
+ int64_t getUniqueId() const override
+ {
+ return d_cconst('d', 'F', 'i', 'H');
+ }
+
+ /* --------------------------------------------------------------------------------------------------------
+ * Init */
+
+ /**
+ Initialize the parameter @a index.
+ This function will be called once, shortly after the plugin is created.
+ */
+ void initParameter(uint32_t index, Parameter& param) override
+ {
+ param.hints = kParameterIsOutput|kParameterIsInteger;
+
+ switch (index)
+ {
+ case kParameterFileSize1:
+ param.name = "Size #1";
+ param.symbol = "size1";
+ break;
+ case kParameterFileSize2:
+ param.name = "Size #2";
+ param.symbol = "size2";
+ break;
+ case kParameterFileSize3:
+ param.name = "Size #3";
+ param.symbol = "size3";
+ break;
+ }
+ }
+
+ /**
+ Set the state key and default value of @a index.@n
+ This function will be called once, shortly after the plugin is created.@n
+ Must be implemented by your plugin class only if DISTRHO_PLUGIN_WANT_STATE is enabled.
+ */
+ void initState(uint32_t index, String& stateKey, String& defaultStateValue) override
+ {
+ switch (index)
+ {
+ case kStateFile1:
+ stateKey = "file1";
+ break;
+ case kStateFile2:
+ stateKey = "file2";
+ break;
+ case kStateFile3:
+ stateKey = "file3";
+ break;
+ }
+
+ defaultStateValue = "";
+ }
+
+ /**
+ TODO API under construction
+ */
+ bool isStateFile(uint32_t index) override
+ {
+ switch (index)
+ {
+ case kStateFile1:
+ case kStateFile2:
+ case kStateFile3:
+ return true;
+ }
+
+ return false;
+ }
+
+ /* --------------------------------------------------------------------------------------------------------
+ * Internal data */
+
+ /**
+ Get the current value of a parameter.
+ The host may call this function from any context, including realtime processing.
+ We have no parameters in this plugin example, so we do nothing with the function.
+ */
+ float getParameterValue(uint32_t index) const override
+ {
+ return fParameters[index];
+ }
+
+ /**
+ Change a parameter value.@n
+ The host may call this function from any context, including realtime processing.
+
+ This function will only be called for parameter inputs.
+ Since we have no parameters inputs in this example, so we do nothing with the function.
+ */
+ void setParameterValue(uint32_t, float) override {}
+
+ /**
+ Change an internal state @a key to @a value.
+ */
+ void setState(const char* key, const char* value) override
+ {
+ d_stdout("DSP setState %s %s", key, value);
+ int fileId = -1;
+
+ /**/ if (std::strcmp(key, "file1") == 0)
+ fileId = 0;
+ else if (std::strcmp(key, "file2") == 0)
+ fileId = 1;
+ else if (std::strcmp(key, "file3") == 0)
+ fileId = 2;
+
+ if (fileId == -1)
+ return;
+
+ if (FILE* const fh = fopen(value, "r"))
+ {
+ fseek(fh, 0, SEEK_END);
+
+ // filesize
+ const long int size = ftell(fh);
+ d_stdout("size of %s is %li", value, size);
+ fParameters[kParameterFileSize1 + fileId] = static_cast<float>(size) / 1000.0f;
+
+ fclose(fh);
+ }
+ }
+
+ /* --------------------------------------------------------------------------------------------------------
+ * Audio/MIDI Processing */
+
+ /**
+ Run/process function for plugins without MIDI input.
+ @note Some parameters might be null if there are no audio inputs or outputs.
+ */
+ void run(const float** inputs, float** outputs, uint32_t frames) override
+ {
+ /**
+ This plugin doesn't do audio, it just demonstrates file handling usage.
+ So here we directly copy inputs over outputs, leaving the audio untouched.
+ We need to be careful in case the host re-uses the same buffer for both ins and outs.
+ */
+ if (outputs[0] != inputs[0])
+ std::memcpy(outputs[0], inputs[0], sizeof(float)*frames);
+ }
+
+ // -------------------------------------------------------------------------------------------------------
+
+private:
+ float fParameters[kParameterCount];
+
+ /**
+ Set our plugin class as non-copyable and add a leak detector just in case.
+ */
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FileHandlingExamplePlugin)
+};
+
+/* ------------------------------------------------------------------------------------------------------------
+ * Plugin entry point, called by DPF to create a new plugin instance. */
+
+Plugin* createPlugin()
+{
+ return new FileHandlingExamplePlugin();
+}
+
+// -----------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DISTRHO
diff --git a/examples/FileHandling/FileHandlingUI.cpp b/examples/FileHandling/FileHandlingUI.cpp
@@ -0,0 +1,269 @@
+/*
+ * DISTRHO Plugin Framework (DPF)
+ * Copyright (C) 2012-2020 Filipe Coelho <falktx@falktx.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any purpose with
+ * or without fee is hereby granted, provided that the above copyright notice and this
+ * permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "DistrhoUI.hpp"
+
+#include "extra/String.hpp"
+
+#include "DistrhoPluginInfo.h"
+#include "NanoButton.hpp"
+
+START_NAMESPACE_DISTRHO
+
+const char* kStateKeys[kStateCount] = {
+ "file1",
+ "file2",
+ "file3",
+};
+
+// -----------------------------------------------------------------------------------------------------------
+
+static void setupButton(Button& btn, int y)
+{
+ btn.setAbsolutePos(5, y);
+ btn.setLabel("Open...");
+ btn.setSize(100, 30);
+}
+
+class FileHandlingExampleUI : public UI,
+ public Button::Callback
+{
+public:
+ static const uint kInitialWidth = 600;
+ static const uint kInitialHeight = 350;
+
+ FileHandlingExampleUI()
+ : UI(kInitialWidth, kInitialHeight),
+ fButton1(this, this),
+ fButton2(this, this),
+ fButton3(this, this),
+ fScale(1.0f)
+ {
+ std::memset(fParameters, 0, sizeof(fParameters));
+ std::memset(fStrBuf, 0, sizeof(fStrBuf));
+
+ setupButton(fButton1, 5);
+ setupButton(fButton2, 105);
+ setupButton(fButton3, 205);
+
+#ifdef DGL_NO_SHARED_RESOURCES
+ createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf");
+#else
+ loadSharedResources();
+#endif
+
+ setGeometryConstraints(kInitialWidth, kInitialHeight, true);
+ }
+
+protected:
+ /* --------------------------------------------------------------------------------------------------------
+ * DSP/Plugin Callbacks */
+
+ /**
+ A parameter has changed on the plugin side.@n
+ This is called by the host to inform the UI about parameter changes.
+ */
+ void parameterChanged(uint32_t index, float value) override
+ {
+ fParameters[index] = value;
+ repaint();
+ }
+
+ /**
+ A state has changed on the plugin side.@n
+ This is called by the host to inform the UI about state changes.
+ */
+ void stateChanged(const char* key, const char* value) override
+ {
+ States stateId = kStateCount;
+
+ /**/ if (std::strcmp(key, "file1") == 0)
+ stateId = kStateFile1;
+ else if (std::strcmp(key, "file2") == 0)
+ stateId = kStateFile2;
+ else if (std::strcmp(key, "file3") == 0)
+ stateId = kStateFile3;
+
+ if (stateId == kStateCount)
+ return;
+
+ fState[stateId] = value;
+ repaint();
+ }
+
+ /* --------------------------------------------------------------------------------------------------------
+ * Widget Callbacks */
+
+ /**
+ The NanoVG drawing function.
+ */
+ void onNanoDisplay() override
+ {
+ const float lineHeight = 20 * fScale;
+ float y;
+
+ fontSize(15.0f * fScale);
+ textLineHeight(lineHeight);
+
+ // ---------------------------------------------------------------------------------------
+ // File 1
+
+ y = 45.0f * fScale;
+
+ if (fState[kStateFile1].isNotEmpty())
+ {
+ drawLeft(0.0f, y, "Name:");
+ drawRight(0.0f, y, fState[kStateFile1]);
+ y += lineHeight;
+
+ drawLeft(0.0f, y, "Size:");
+ drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize1]));
+ y += lineHeight;
+ }
+ else
+ {
+ drawLeft(0.0f, y, "No file loaded");
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // File 2
+
+ y = 145.0f * fScale;
+
+ if (fState[kStateFile2].isNotEmpty())
+ {
+ drawLeft(0.0f, y, "Name:");
+ drawRight(0.0f, y, fState[kStateFile2]);
+ y += lineHeight;
+
+ drawLeft(0.0f, y, "Size:");
+ drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize2]));
+ y += lineHeight;
+ }
+ else
+ {
+ drawLeft(0.0f, y, "No file loaded");
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // File 3
+
+ y = 245.0f * fScale;
+
+ if (fState[kStateFile3].isNotEmpty())
+ {
+ drawLeft(0.0f, y, "Name:");
+ drawRight(0.0f, y, fState[kStateFile3]);
+ y += lineHeight;
+
+ drawLeft(0.0f, y, "Size:");
+ drawRight(0.0f, y, getTextBufFileSize(fParameters[kParameterFileSize3]));
+ y += lineHeight;
+ }
+ else
+ {
+ drawLeft(0.0f, y, "No file loaded");
+ }
+ }
+
+ void onResize(const ResizeEvent& ev) override
+ {
+ fScale = static_cast<float>(ev.size.getHeight())/kInitialHeight;
+
+ UI::onResize(ev);
+ }
+
+ void buttonClicked(Button* const button, bool) override
+ {
+ States stateId = kStateCount;
+
+ /**/ if (button == &fButton1)
+ stateId = kStateFile1;
+ else if (button == &fButton2)
+ stateId = kStateFile2;
+ else if (button == &fButton3)
+ stateId = kStateFile3;
+
+ if (stateId == kStateCount)
+ return;
+
+ requestStateFile(kStateKeys[stateId]);
+ }
+
+ // -------------------------------------------------------------------------------------------------------
+
+private:
+ // Parameters
+ float fParameters[kParameterCount];
+
+ // State (files)
+ String fState[kStateCount];
+ Button fButton1, fButton2, fButton3;
+
+ // UI stuff
+ float fScale;
+
+ // temp buf for text
+ char fStrBuf[0xff];
+
+ // helpers for putting text into fStrBuf and returning it
+ const char* getTextBufFileSize(const float value)
+ {
+ /**/ if (value > 1024*1024)
+ std::snprintf(fStrBuf, 0xfe, "%.2f GiB", value/(1024*1024));
+ else if (value > 1024)
+ std::snprintf(fStrBuf, 0xfe, "%.2f MiB", value/1024);
+ else
+ std::snprintf(fStrBuf, 0xfe, "%.2f KiB", value);
+ return fStrBuf;
+ }
+
+ // helpers for drawing text
+ void drawLeft(const float x, const float y, const char* const text)
+ {
+ beginPath();
+ fillColor(200, 200, 200);
+ textAlign(ALIGN_RIGHT|ALIGN_TOP);
+ textBox(x, y, 100 * fScale, text);
+ closePath();
+ }
+
+ void drawRight(const float x, const float y, const char* const text)
+ {
+ beginPath();
+ fillColor(255, 255, 255);
+ textAlign(ALIGN_LEFT|ALIGN_TOP);
+ textBox(x + (105 * fScale), y, (kInitialWidth - x) * fScale, text);
+ closePath();
+ }
+
+ /**
+ Set our UI class as non-copyable and add a leak detector just in case.
+ */
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FileHandlingExampleUI)
+};
+
+/* ------------------------------------------------------------------------------------------------------------
+ * UI entry point, called by DPF to create a new UI instance. */
+
+UI* createUI()
+{
+ return new FileHandlingExampleUI();
+}
+
+// -----------------------------------------------------------------------------------------------------------
+
+END_NAMESPACE_DISTRHO
diff --git a/examples/FileHandling/Makefile b/examples/FileHandling/Makefile
@@ -0,0 +1,46 @@
+#!/usr/bin/make -f
+# Makefile for DISTRHO Plugins #
+# ---------------------------- #
+# Created by falkTX
+#
+
+# --------------------------------------------------------------
+# Project name, used for binaries
+
+NAME = d_files
+
+# --------------------------------------------------------------
+# Files to build
+
+FILES_DSP = \
+ FileHandlingPlugin.cpp
+
+FILES_UI = \
+ FileHandlingUI.cpp \
+ NanoButton.cpp
+
+# --------------------------------------------------------------
+# Do some magic
+
+include ../../Makefile.plugins.mk
+
+# --------------------------------------------------------------
+# Enable all possible plugin types
+
+ifeq ($(HAVE_JACK),true)
+ifeq ($(HAVE_OPENGL),true)
+TARGETS += jack
+endif
+endif
+
+ifeq ($(HAVE_OPENGL),true)
+TARGETS += lv2_sep
+else
+TARGETS += lv2_dsp
+endif
+
+TARGETS += vst
+
+all: $(TARGETS)
+
+# --------------------------------------------------------------
diff --git a/examples/FileHandling/NanoButton.cpp b/examples/FileHandling/NanoButton.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018-2019 Rob van den Berg <rghvdberg at gmail dot org>
+ *
+ * This file is part of CharacterCompressor
+ *
+ * Nnjas2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CharacterCompressor is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CharacterCompressor. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "NanoButton.hpp"
+#include "Window.hpp"
+
+START_NAMESPACE_DISTRHO
+
+Button::Button(Widget *parent, Callback *cb)
+ : NanoWidget(parent),
+ fCallback(cb),
+ buttonActive(false)
+{
+ loadSharedResources();
+ fNanoFont = findFont(NANOVG_DEJAVU_SANS_TTF);
+ labelColor = Color(255, 255, 255);
+ backgroundColor = Color(32,32,32);
+ Label = "button";
+}
+
+void Button::onNanoDisplay()
+{
+ auto w = getWidth();
+ auto h = getHeight();
+ auto margin = 1.0f;
+
+ // Background
+ beginPath();
+ fillColor(backgroundColor);
+ strokeColor(borderColor);
+ rect(margin, margin, w - 2 * margin, h-2*margin);
+ fill();
+ stroke();
+ closePath();
+
+ //Label
+ beginPath();
+ fontFaceId(fNanoFont);
+ fontSize(14);
+ fillColor(labelColor);
+ Rectangle<float> bounds;
+ textBounds(0, 0, Label.c_str(), NULL, bounds);
+ // float tw = bounds.getWidth();
+ // float th = bounds.getHeight();
+ float tx = w / 2.0f ;
+ float ty = h / 2.0f;
+ textAlign(ALIGN_CENTER | ALIGN_MIDDLE);
+
+ fillColor(255, 255, 255, 255);
+ text(tx, ty, Label.c_str(), NULL);
+ closePath();
+}
+
+void Button::setLabel(std::string label)
+{
+ Label = label;
+}
+
+void Button::setLabelColor(const Color color)
+{
+ labelColor = color;
+ borderColor = color;
+}
+void Button::setBackgroundColor(const Color color)
+{
+ backgroundColor = color;
+}
+
+bool Button::onMouse(const MouseEvent &ev)
+{
+ if (ev.press & contains(ev.pos))
+ {
+ buttonActive = true;
+ setLabelColor(labelColor);
+ fCallback->buttonClicked(this, true);
+ return true;
+ }
+ else if (buttonActive)
+ {
+ buttonActive = false;
+ //setLabelColor(Color(128,128,128));
+ return true;
+ }
+
+ return false;
+}
+
+END_NAMESPACE_DISTRHO
diff --git a/examples/FileHandling/NanoButton.hpp b/examples/FileHandling/NanoButton.hpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018-2019 Rob van den Berg <rghvdberg at gmail dot org>
+ *
+ * This file is part of CharacterCompressor
+ *
+ * Nnjas2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CharacterCompressor is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CharacterCompressor. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef BUTTON_HPP_INCLUDED
+#define BUTTON_HPP_INCLUDED
+
+#include "Widget.hpp"
+#include "NanoVG.hpp"
+
+#include <string>
+
+START_NAMESPACE_DISTRHO
+
+class Button : public NanoWidget
+{
+public:
+ class Callback
+ {
+ public:
+ virtual ~Callback() {}
+ virtual void buttonClicked(Button *button, bool value) = 0;
+ };
+ explicit Button(Widget *parent, Callback *cb);
+
+ void setLabel(std::string label);
+ void setLabelColor(Color color);
+ void setBackgroundColor(Color color);
+
+protected:
+ void onNanoDisplay() override;
+ bool onMouse(const MouseEvent &ev) override;
+
+private:
+ std::string Label;
+ Color labelColor,backgroundColor,borderColor;
+ Callback *const fCallback;
+ bool buttonActive;
+ FontId fNanoFont;
+ DISTRHO_LEAK_DETECTOR(Button)
+};
+
+END_NAMESPACE_DISTRHO
+
+#endif