commit 7baa2c0458c2968d32bd37e34b0e3f54c1a368ff
parent e46dd357b642654240b5539b0e831178fd22e343
Author: falkTX <falktx@falktx.com>
Date: Fri, 21 May 2021 19:13:40 +0100
Move ImageWidgets code to generic file, WIP
Diffstat:
7 files changed, 1069 insertions(+), 1080 deletions(-)
diff --git a/dgl/Cairo.hpp b/dgl/Cairo.hpp
@@ -19,7 +19,6 @@
#include "ImageBase.hpp"
#include "ImageBaseWidgets.hpp"
-#include "SubWidget.hpp"
#include <cairo/cairo.h>
@@ -115,25 +114,21 @@ class CairoBaseWidget : public BaseWidget
public:
/**
Constructor for a CairoSubWidget.
- @see CreateFlags
*/
explicit CairoBaseWidget(Widget* const parentGroupWidget);
/**
Constructor for a CairoTopLevelWidget.
- @see CreateFlags
*/
explicit CairoBaseWidget(Window& windowToMapTo);
/**
Constructor for a CairoStandaloneWindow without parent window.
- @see CreateFlags
*/
explicit CairoBaseWidget(Application& app);
/**
Constructor for a CairoStandaloneWindow with parent window.
- @see CreateFlags
*/
explicit CairoBaseWidget(Application& app, Window& parentWindow);
@@ -171,6 +166,9 @@ typedef CairoBaseWidget<StandaloneWindow> CairoStandaloneWindow;
typedef ImageBaseAboutWindow<CairoImage> CairoImageAboutWindow;
typedef ImageBaseButton<CairoImage> CairoImageButton;
+typedef ImageBaseKnob<CairoImage> CairoImageKnob;
+typedef ImageBaseSlider<CairoImage> CairoImageSlider;
+typedef ImageBaseSwitch<CairoImage> CairoImageSwitch;
// --------------------------------------------------------------------------------------------------------------------
diff --git a/dgl/ImageBaseWidgets.hpp b/dgl/ImageBaseWidgets.hpp
@@ -82,6 +82,205 @@ private:
// --------------------------------------------------------------------------------------------------------------------
+template <class ImageType>
+class ImageBaseKnob : public SubWidget
+{
+public:
+ enum Orientation {
+ Horizontal,
+ Vertical
+ };
+
+ class Callback
+ {
+ public:
+ virtual ~Callback() {}
+ virtual void imageKnobDragStarted(ImageBaseKnob* imageKnob) = 0;
+ virtual void imageKnobDragFinished(ImageBaseKnob* imageKnob) = 0;
+ virtual void imageKnobValueChanged(ImageBaseKnob* imageKnob, float value) = 0;
+ };
+
+ explicit ImageBaseKnob(Widget* parentWidget, const ImageType& image, Orientation orientation = Vertical) noexcept;
+ explicit ImageBaseKnob(const ImageBaseKnob& imageKnob);
+ ImageBaseKnob& operator=(const ImageBaseKnob& imageKnob);
+ ~ImageBaseKnob() override;
+
+ float getValue() const noexcept;
+
+ void setDefault(float def) noexcept;
+ void setRange(float min, float max) noexcept;
+ void setStep(float step) noexcept;
+ void setValue(float value, bool sendCallback = false) noexcept;
+ void setUsingLogScale(bool yesNo) noexcept;
+
+ void setCallback(Callback* callback) noexcept;
+ void setOrientation(Orientation orientation) noexcept;
+ void setRotationAngle(int angle);
+
+ void setImageLayerCount(uint count) noexcept;
+
+protected:
+ void onDisplay() override;
+ bool onMouse(const MouseEvent&) override;
+ bool onMotion(const MotionEvent&) override;
+ bool onScroll(const ScrollEvent&) override;
+
+private:
+ struct PrivateData;
+ PrivateData* const pData;
+
+ /*
+ Image fImage;
+ float fMinimum;
+ float fMaximum;
+ float fStep;
+ float fValue;
+ float fValueDef;
+ float fValueTmp;
+ bool fUsingDefault;
+ bool fUsingLog;
+ Orientation fOrientation;
+
+ int fRotationAngle;
+ bool fDragging;
+ int fLastX;
+ int fLastY;
+
+ Callback* fCallback;
+
+ bool fIsImgVertical;
+ uint fImgLayerWidth;
+ uint fImgLayerHeight;
+ uint fImgLayerCount;
+ bool fIsReady;
+ GLuint fTextureId;
+
+ float _logscale(float value) const;
+ float _invlogscale(float value) const;
+ */
+
+ DISTRHO_LEAK_DETECTOR(ImageBaseKnob)
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+// note set range and step before setting the value
+
+template <class ImageType>
+class ImageBaseSlider : public SubWidget
+{
+public:
+ class Callback
+ {
+ public:
+ virtual ~Callback() {}
+ virtual void imageSliderDragStarted(ImageBaseSlider* imageSlider) = 0;
+ virtual void imageSliderDragFinished(ImageBaseSlider* imageSlider) = 0;
+ virtual void imageSliderValueChanged(ImageBaseSlider* imageSlider, float value) = 0;
+ };
+
+ explicit ImageBaseSlider(Widget* parentWidget, const ImageType& image) noexcept;
+
+ float getValue() const noexcept;
+ void setValue(float value, bool sendCallback = false) noexcept;
+ void setDefault(float def) noexcept;
+
+ void setStartPos(const Point<int>& startPos) noexcept;
+ void setStartPos(int x, int y) noexcept;
+ void setEndPos(const Point<int>& endPos) noexcept;
+ void setEndPos(int x, int y) noexcept;
+
+ void setInverted(bool inverted) noexcept;
+ void setRange(float min, float max) noexcept;
+ void setStep(float step) noexcept;
+
+ void setCallback(Callback* callback) noexcept;
+
+protected:
+ void onDisplay() override;
+ bool onMouse(const MouseEvent&) override;
+ bool onMotion(const MotionEvent&) override;
+
+private:
+ struct PrivateData;
+ PrivateData* const pData;
+
+ /*
+ Image fImage;
+ float fMinimum;
+ float fMaximum;
+ float fStep;
+ float fValue;
+ float fValueDef;
+ float fValueTmp;
+ bool fUsingDefault;
+
+ bool fDragging;
+ bool fInverted;
+ bool fValueIsSet;
+ int fStartedX;
+ int fStartedY;
+
+ Callback* fCallback;
+
+ Point<int> fStartPos;
+ Point<int> fEndPos;
+ Rectangle<double> fSliderArea;
+
+ void _recheckArea() noexcept;
+ */
+
+ // these should not be used
+ void setAbsoluteX(int) const noexcept {}
+ void setAbsoluteY(int) const noexcept {}
+ void setAbsolutePos(int, int) const noexcept {}
+ void setAbsolutePos(const Point<int>&) const noexcept {}
+
+ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageBaseSlider)
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
+template <class ImageType>
+class ImageBaseSwitch : public SubWidget
+{
+public:
+ class Callback
+ {
+ public:
+ virtual ~Callback() {}
+ virtual void imageSwitchClicked(ImageBaseSwitch* imageSwitch, bool down) = 0;
+ };
+
+ explicit ImageBaseSwitch(Widget* parentWidget, const ImageType& imageNormal, const ImageType& imageDown) noexcept;
+ explicit ImageBaseSwitch(const ImageBaseSwitch& imageSwitch) noexcept;
+ ImageBaseSwitch& operator=(const ImageBaseSwitch& imageSwitch) noexcept;
+
+ bool isDown() const noexcept;
+ void setDown(bool down) noexcept;
+
+ void setCallback(Callback* callback) noexcept;
+
+protected:
+ void onDisplay() override;
+ bool onMouse(const MouseEvent&) override;
+
+private:
+ struct PrivateData;
+ PrivateData* const pData;
+
+ /*
+ Image fImageNormal;
+ Image fImageDown;
+ bool fIsDown;
+ Callback* fCallback;
+ */
+
+ DISTRHO_LEAK_DETECTOR(ImageBaseSwitch)
+};
+
+// --------------------------------------------------------------------------------------------------------------------
+
END_NAMESPACE_DGL
#endif // DGL_IMAGE_BASE_WIDGETS_HPP_INCLUDED
diff --git a/dgl/ImageWidgets.hpp b/dgl/ImageWidgets.hpp
@@ -17,206 +17,25 @@
#ifndef DGL_IMAGE_WIDGETS_HPP_INCLUDED
#define DGL_IMAGE_WIDGETS_HPP_INCLUDED
-#include "Image.hpp"
-#include "ImageBaseWidgets.hpp"
-#include "SubWidget.hpp"
-
-// TODO switch to use templated image type after merging widget-related PRs
-#if defined(__GNUC__) && (__GNUC__ >= 6)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
+#include "OpenGL.hpp"
START_NAMESPACE_DGL
-// -----------------------------------------------------------------------
-
-class ImageKnob : public SubWidget
-{
-public:
- enum Orientation {
- Horizontal,
- Vertical
- };
-
- class Callback
- {
- public:
- virtual ~Callback() {}
- virtual void imageKnobDragStarted(ImageKnob* imageKnob) = 0;
- virtual void imageKnobDragFinished(ImageKnob* imageKnob) = 0;
- virtual void imageKnobValueChanged(ImageKnob* imageKnob, float value) = 0;
- };
-
- explicit ImageKnob(Widget* parentWidget, const Image& image, Orientation orientation = Vertical) noexcept;
- explicit ImageKnob(const ImageKnob& imageKnob);
- ImageKnob& operator=(const ImageKnob& imageKnob);
- ~ImageKnob() override;
-
- float getValue() const noexcept;
-
- void setDefault(float def) noexcept;
- void setRange(float min, float max) noexcept;
- void setStep(float step) noexcept;
- void setValue(float value, bool sendCallback = false) noexcept;
- void setUsingLogScale(bool yesNo) noexcept;
-
- void setCallback(Callback* callback) noexcept;
- void setOrientation(Orientation orientation) noexcept;
- void setRotationAngle(int angle);
-
- void setImageLayerCount(uint count) noexcept;
-
-protected:
- void onDisplay() override;
- bool onMouse(const MouseEvent&) override;
- bool onMotion(const MotionEvent&) override;
- bool onScroll(const ScrollEvent&) override;
-
-private:
- Image fImage;
- float fMinimum;
- float fMaximum;
- float fStep;
- float fValue;
- float fValueDef;
- float fValueTmp;
- bool fUsingDefault;
- bool fUsingLog;
- Orientation fOrientation;
-
- int fRotationAngle;
- bool fDragging;
- int fLastX;
- int fLastY;
-
- Callback* fCallback;
-
- bool fIsImgVertical;
- uint fImgLayerWidth;
- uint fImgLayerHeight;
- uint fImgLayerCount;
- bool fIsReady;
- GLuint fTextureId;
-
- float _logscale(float value) const;
- float _invlogscale(float value) const;
-
- DISTRHO_LEAK_DETECTOR(ImageKnob)
-};
-
-// -----------------------------------------------------------------------
-
-// note set range and step before setting the value
-
-class ImageSlider : public SubWidget
-{
-public:
- class Callback
- {
- public:
- virtual ~Callback() {}
- virtual void imageSliderDragStarted(ImageSlider* imageSlider) = 0;
- virtual void imageSliderDragFinished(ImageSlider* imageSlider) = 0;
- virtual void imageSliderValueChanged(ImageSlider* imageSlider, float value) = 0;
- };
-
- explicit ImageSlider(Widget* parentWidget, const Image& image) noexcept;
+DISTRHO_DEPRECATED_BY("OpenGLImageAboutWindow")
+typedef OpenGLImageAboutWindow ImageAboutWindow;
- float getValue() const noexcept;
- void setValue(float value, bool sendCallback = false) noexcept;
- void setDefault(float def) noexcept;
+DISTRHO_DEPRECATED_BY("OpenGLImageButton")
+typedef OpenGLImageButton ImageButton;
- void setStartPos(const Point<int>& startPos) noexcept;
- void setStartPos(int x, int y) noexcept;
- void setEndPos(const Point<int>& endPos) noexcept;
- void setEndPos(int x, int y) noexcept;
+DISTRHO_DEPRECATED_BY("OpenGLImageKnob")
+typedef OpenGLImageKnob ImageKnob;
- void setInverted(bool inverted) noexcept;
- void setRange(float min, float max) noexcept;
- void setStep(float step) noexcept;
+DISTRHO_DEPRECATED_BY("OpenGLImageSlider")
+typedef OpenGLImageSlider ImageSlider;
- void setCallback(Callback* callback) noexcept;
-
-protected:
- void onDisplay() override;
- bool onMouse(const MouseEvent&) override;
- bool onMotion(const MotionEvent&) override;
-
-private:
- Image fImage;
- float fMinimum;
- float fMaximum;
- float fStep;
- float fValue;
- float fValueDef;
- float fValueTmp;
- bool fUsingDefault;
-
- bool fDragging;
- bool fInverted;
- bool fValueIsSet;
- int fStartedX;
- int fStartedY;
-
- Callback* fCallback;
-
- Point<int> fStartPos;
- Point<int> fEndPos;
- Rectangle<double> fSliderArea;
-
- void _recheckArea() noexcept;
-
- // these should not be used
- void setAbsoluteX(int) const noexcept {}
- void setAbsoluteY(int) const noexcept {}
- void setAbsolutePos(int, int) const noexcept {}
- void setAbsolutePos(const Point<int>&) const noexcept {}
-
- DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageSlider)
-};
-
-// -----------------------------------------------------------------------
-
-class ImageSwitch : public SubWidget
-{
-public:
- class Callback
- {
- public:
- virtual ~Callback() {}
- virtual void imageSwitchClicked(ImageSwitch* imageSwitch, bool down) = 0;
- };
-
- explicit ImageSwitch(Widget* parentWidget, const Image& imageNormal, const Image& imageDown) noexcept;
- explicit ImageSwitch(const ImageSwitch& imageSwitch) noexcept;
- ImageSwitch& operator=(const ImageSwitch& imageSwitch) noexcept;
-
- bool isDown() const noexcept;
- void setDown(bool down) noexcept;
-
- void setCallback(Callback* callback) noexcept;
-
-protected:
- void onDisplay() override;
- bool onMouse(const MouseEvent&) override;
-
-private:
- Image fImageNormal;
- Image fImageDown;
- bool fIsDown;
-
- Callback* fCallback;
-
- DISTRHO_LEAK_DETECTOR(ImageSwitch)
-};
-
-// -----------------------------------------------------------------------
+DISTRHO_DEPRECATED_BY("OpenGLImageSwitch")
+typedef OpenGLImageSwitch ImageSwitch;
END_NAMESPACE_DGL
-#if defined(__GNUC__) && (__GNUC__ >= 6)
-# pragma GCC diagnostic pop
-#endif
-
#endif // DGL_IMAGE_WIDGETS_HPP_INCLUDED
diff --git a/dgl/Makefile b/dgl/Makefile
@@ -56,7 +56,6 @@ endif
OBJS_opengl = $(OBJS_common) \
../build/dgl/OpenGL.cpp.opengl.o \
- ../build/dgl/ImageWidgets.cpp.o \
../build/dgl/NanoVG.cpp.opengl.o
ifeq ($(MACOS),true)
diff --git a/dgl/OpenGL.hpp b/dgl/OpenGL.hpp
@@ -282,12 +282,9 @@ private:
typedef ImageBaseAboutWindow<OpenGLImage> OpenGLImageAboutWindow;
typedef ImageBaseButton<OpenGLImage> OpenGLImageButton;
-
-DISTRHO_DEPRECATED_BY("OpenGLImageAboutWindow")
-typedef OpenGLImageAboutWindow ImageAboutWindow;
-
-DISTRHO_DEPRECATED_BY("OpenGLImageButton")
-typedef OpenGLImageButton ImageButton;
+typedef ImageBaseKnob<OpenGLImage> OpenGLImageKnob;
+typedef ImageBaseSlider<OpenGLImage> OpenGLImageSlider;
+typedef ImageBaseSwitch<OpenGLImage> OpenGLImageSwitch;
// -----------------------------------------------------------------------
diff --git a/dgl/src/ImageBaseWidgets.cpp b/dgl/src/ImageBaseWidgets.cpp
@@ -180,4 +180,857 @@ bool ImageBaseButton<ImageType>::onMotion(const MotionEvent& ev)
// --------------------------------------------------------------------------------------------------------------------
+#if 0
+ImageKnob::ImageKnob(Widget* const parentWidget, const Image& image, Orientation orientation) noexcept
+ : SubWidget(parentWidget),
+ fImage(image),
+ fMinimum(0.0f),
+ fMaximum(1.0f),
+ fStep(0.0f),
+ fValue(0.5f),
+ fValueDef(fValue),
+ fValueTmp(fValue),
+ fUsingDefault(false),
+ fUsingLog(false),
+ fOrientation(orientation),
+ fRotationAngle(0),
+ fDragging(false),
+ fLastX(0),
+ fLastY(0),
+ fCallback(nullptr),
+ fIsImgVertical(image.getHeight() > image.getWidth()),
+ fImgLayerWidth(fIsImgVertical ? image.getWidth() : image.getHeight()),
+ fImgLayerHeight(fImgLayerWidth),
+ fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerHeight : image.getWidth()/fImgLayerWidth),
+ fIsReady(false),
+ fTextureId(0)
+{
+ glGenTextures(1, &fTextureId);
+ setSize(fImgLayerWidth, fImgLayerHeight);
+}
+
+ImageKnob::ImageKnob(const ImageKnob& imageKnob)
+ : SubWidget(imageKnob.getParentWidget()),
+ fImage(imageKnob.fImage),
+ fMinimum(imageKnob.fMinimum),
+ fMaximum(imageKnob.fMaximum),
+ fStep(imageKnob.fStep),
+ fValue(imageKnob.fValue),
+ fValueDef(imageKnob.fValueDef),
+ fValueTmp(fValue),
+ fUsingDefault(imageKnob.fUsingDefault),
+ fUsingLog(imageKnob.fUsingLog),
+ fOrientation(imageKnob.fOrientation),
+ fRotationAngle(imageKnob.fRotationAngle),
+ fDragging(false),
+ fLastX(0),
+ fLastY(0),
+ fCallback(imageKnob.fCallback),
+ fIsImgVertical(imageKnob.fIsImgVertical),
+ fImgLayerWidth(imageKnob.fImgLayerWidth),
+ fImgLayerHeight(imageKnob.fImgLayerHeight),
+ fImgLayerCount(imageKnob.fImgLayerCount),
+ fIsReady(false),
+ fTextureId(0)
+{
+ glGenTextures(1, &fTextureId);
+ setSize(fImgLayerWidth, fImgLayerHeight);
+}
+
+ImageKnob& ImageKnob::operator=(const ImageKnob& imageKnob)
+{
+ fImage = imageKnob.fImage;
+ fMinimum = imageKnob.fMinimum;
+ fMaximum = imageKnob.fMaximum;
+ fStep = imageKnob.fStep;
+ fValue = imageKnob.fValue;
+ fValueDef = imageKnob.fValueDef;
+ fValueTmp = fValue;
+ fUsingDefault = imageKnob.fUsingDefault;
+ fUsingLog = imageKnob.fUsingLog;
+ fOrientation = imageKnob.fOrientation;
+ fRotationAngle = imageKnob.fRotationAngle;
+ fDragging = false;
+ fLastX = 0;
+ fLastY = 0;
+ fCallback = imageKnob.fCallback;
+ fIsImgVertical = imageKnob.fIsImgVertical;
+ fImgLayerWidth = imageKnob.fImgLayerWidth;
+ fImgLayerHeight = imageKnob.fImgLayerHeight;
+ fImgLayerCount = imageKnob.fImgLayerCount;
+ fIsReady = false;
+
+ if (fTextureId != 0)
+ {
+ glDeleteTextures(1, &fTextureId);
+ fTextureId = 0;
+ }
+
+ glGenTextures(1, &fTextureId);
+ setSize(fImgLayerWidth, fImgLayerHeight);
+
+ return *this;
+}
+
+ImageKnob::~ImageKnob()
+{
+ if (fTextureId != 0)
+ {
+ glDeleteTextures(1, &fTextureId);
+ fTextureId = 0;
+ }
+}
+
+float ImageKnob::getValue() const noexcept
+{
+ return fValue;
+}
+
+// NOTE: value is assumed to be scaled if using log
+void ImageKnob::setDefault(float value) noexcept
+{
+ fValueDef = value;
+ fUsingDefault = true;
+}
+
+void ImageKnob::setRange(float min, float max) noexcept
+{
+ DISTRHO_SAFE_ASSERT_RETURN(max > min,);
+
+ if (fValue < min)
+ {
+ fValue = min;
+ repaint();
+
+ if (fCallback != nullptr)
+ {
+ try {
+ fCallback->imageKnobValueChanged(this, fValue);
+ } DISTRHO_SAFE_EXCEPTION("ImageKnob::setRange < min");
+ }
+ }
+ else if (fValue > max)
+ {
+ fValue = max;
+ repaint();
+
+ if (fCallback != nullptr)
+ {
+ try {
+ fCallback->imageKnobValueChanged(this, fValue);
+ } DISTRHO_SAFE_EXCEPTION("ImageKnob::setRange > max");
+ }
+ }
+
+ fMinimum = min;
+ fMaximum = max;
+}
+
+void ImageKnob::setStep(float step) noexcept
+{
+ fStep = step;
+}
+
+// NOTE: value is assumed to be scaled if using log
+void ImageKnob::setValue(float value, bool sendCallback) noexcept
+{
+ if (d_isEqual(fValue, value))
+ return;
+
+ fValue = value;
+
+ if (d_isZero(fStep))
+ fValueTmp = value;
+
+ if (fRotationAngle == 0)
+ fIsReady = false;
+
+ repaint();
+
+ if (sendCallback && fCallback != nullptr)
+ {
+ try {
+ fCallback->imageKnobValueChanged(this, fValue);
+ } DISTRHO_SAFE_EXCEPTION("ImageKnob::setValue");
+ }
+}
+
+void ImageKnob::setUsingLogScale(bool yesNo) noexcept
+{
+ fUsingLog = yesNo;
+}
+
+void ImageKnob::setCallback(Callback* callback) noexcept
+{
+ fCallback = callback;
+}
+
+void ImageKnob::setOrientation(Orientation orientation) noexcept
+{
+ if (fOrientation == orientation)
+ return;
+
+ fOrientation = orientation;
+}
+
+void ImageKnob::setRotationAngle(int angle)
+{
+ if (fRotationAngle == angle)
+ return;
+
+ fRotationAngle = angle;
+ fIsReady = false;
+}
+
+void ImageKnob::setImageLayerCount(uint count) noexcept
+{
+ DISTRHO_SAFE_ASSERT_RETURN(count > 1,);
+
+ fImgLayerCount = count;
+
+ if (fIsImgVertical)
+ fImgLayerHeight = fImage.getHeight()/count;
+ else
+ fImgLayerWidth = fImage.getWidth()/count;
+
+ setSize(fImgLayerWidth, fImgLayerHeight);
+}
+
+void ImageKnob::onDisplay()
+{
+ const float normValue = ((fUsingLog ? _invlogscale(fValue) : fValue) - fMinimum) / (fMaximum - fMinimum);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, fTextureId);
+
+ if (! fIsReady)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+
+ static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);
+
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ uint imageDataOffset = 0;
+
+ if (fRotationAngle == 0)
+ {
+ DISTRHO_SAFE_ASSERT_RETURN(fImgLayerCount > 0,);
+ DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);
+
+ const uint& v1(fIsImgVertical ? fImgLayerWidth : fImgLayerHeight);
+ const uint& v2(fIsImgVertical ? fImgLayerHeight : fImgLayerWidth);
+
+ const uint layerDataSize = v1 * v2 * ((fImage.getFormat() == kImageFormatBGRA ||
+ fImage.getFormat() == kImageFormatRGBA) ? 4 : 3);
+ /* */ imageDataOffset = layerDataSize * uint(normValue * float(fImgLayerCount-1));
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
+ asOpenGLImageFormat(fImage.getFormat()), GL_UNSIGNED_BYTE, fImage.getRawData() + imageDataOffset);
+
+ fIsReady = true;
+ }
+
+ const int w = static_cast<int>(getWidth());
+ const int h = static_cast<int>(getHeight());
+
+ if (fRotationAngle != 0)
+ {
+ glPushMatrix();
+
+ const int w2 = w/2;
+ const int h2 = h/2;
+
+ glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
+ glRotatef(normValue*static_cast<float>(fRotationAngle), 0.0f, 0.0f, 1.0f);
+
+ Rectangle<int>(-w2, -h2, w, h).draw();
+
+ glPopMatrix();
+ }
+ else
+ {
+ Rectangle<int>(0, 0, w, h).draw();
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+}
+
+bool ImageKnob::onMouse(const MouseEvent& ev)
+{
+ if (ev.button != 1)
+ return false;
+
+ if (ev.press)
+ {
+ if (! contains(ev.pos))
+ return false;
+
+ if ((ev.mod & kModifierShift) != 0 && fUsingDefault)
+ {
+ setValue(fValueDef, true);
+ fValueTmp = fValue;
+ return true;
+ }
+
+ fDragging = true;
+ fLastX = ev.pos.getX();
+ fLastY = ev.pos.getY();
+
+ if (fCallback != nullptr)
+ fCallback->imageKnobDragStarted(this);
+
+ return true;
+ }
+ else if (fDragging)
+ {
+ if (fCallback != nullptr)
+ fCallback->imageKnobDragFinished(this);
+
+ fDragging = false;
+ return true;
+ }
+
+ return false;
+}
+
+bool ImageKnob::onMotion(const MotionEvent& ev)
+{
+ if (! fDragging)
+ return false;
+
+ bool doVal = false;
+ float d, value = 0.0f;
+
+ if (fOrientation == ImageKnob::Horizontal)
+ {
+ if (const int movX = ev.pos.getX() - fLastX)
+ {
+ d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
+ value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * float(movX));
+ doVal = true;
+ }
+ }
+ else if (fOrientation == ImageKnob::Vertical)
+ {
+ if (const int movY = fLastY - ev.pos.getY())
+ {
+ d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
+ value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * float(movY));
+ doVal = true;
+ }
+ }
+
+ if (! doVal)
+ return false;
+
+ if (fUsingLog)
+ value = _logscale(value);
+
+ if (value < fMinimum)
+ {
+ fValueTmp = value = fMinimum;
+ }
+ else if (value > fMaximum)
+ {
+ fValueTmp = value = fMaximum;
+ }
+ else if (d_isNotZero(fStep))
+ {
+ fValueTmp = value;
+ const float rest = std::fmod(value, fStep);
+ value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
+ }
+
+ setValue(value, true);
+
+ fLastX = ev.pos.getX();
+ fLastY = ev.pos.getY();
+
+ return true;
+}
+
+bool ImageKnob::onScroll(const ScrollEvent& ev)
+{
+ if (! contains(ev.pos))
+ return false;
+
+ const float d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
+ float value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * 10.f * ev.delta.getY());
+
+ if (fUsingLog)
+ value = _logscale(value);
+
+ if (value < fMinimum)
+ {
+ fValueTmp = value = fMinimum;
+ }
+ else if (value > fMaximum)
+ {
+ fValueTmp = value = fMaximum;
+ }
+ else if (d_isNotZero(fStep))
+ {
+ fValueTmp = value;
+ const float rest = std::fmod(value, fStep);
+ value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
+ }
+
+ setValue(value, true);
+ return true;
+}
+
+// -----------------------------------------------------------------------
+
+float ImageKnob::_logscale(float value) const
+{
+ const float b = std::log(fMaximum/fMinimum)/(fMaximum-fMinimum);
+ const float a = fMaximum/std::exp(fMaximum*b);
+ return a * std::exp(b*value);
+}
+
+float ImageKnob::_invlogscale(float value) const
+{
+ const float b = std::log(fMaximum/fMinimum)/(fMaximum-fMinimum);
+ const float a = fMaximum/std::exp(fMaximum*b);
+ return std::log(value/a)/b;
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#if 0
+ImageSlider::ImageSlider(Widget* const parentWidget, const Image& image) noexcept
+ : SubWidget(parentWidget),
+ fImage(image),
+ fMinimum(0.0f),
+ fMaximum(1.0f),
+ fStep(0.0f),
+ fValue(0.5f),
+ fValueDef(fValue),
+ fValueTmp(fValue),
+ fUsingDefault(false),
+ fDragging(false),
+ fInverted(false),
+ fValueIsSet(false),
+ fStartedX(0),
+ fStartedY(0),
+ fCallback(nullptr),
+ fStartPos(),
+ fEndPos(),
+ fSliderArea()
+{
+ setNeedsFullViewportDrawing();
+}
+
+float ImageSlider::getValue() const noexcept
+{
+ return fValue;
+}
+
+void ImageSlider::setValue(float value, bool sendCallback) noexcept
+{
+ if (! fValueIsSet)
+ fValueIsSet = true;
+
+ if (d_isEqual(fValue, value))
+ return;
+
+ fValue = value;
+
+ if (d_isZero(fStep))
+ fValueTmp = value;
+
+ repaint();
+
+ if (sendCallback && fCallback != nullptr)
+ {
+ try {
+ fCallback->imageSliderValueChanged(this, fValue);
+ } DISTRHO_SAFE_EXCEPTION("ImageSlider::setValue");
+ }
+}
+
+void ImageSlider::setStartPos(const Point<int>& startPos) noexcept
+{
+ fStartPos = startPos;
+ _recheckArea();
+}
+
+void ImageSlider::setStartPos(int x, int y) noexcept
+{
+ setStartPos(Point<int>(x, y));
+}
+
+void ImageSlider::setEndPos(const Point<int>& endPos) noexcept
+{
+ fEndPos = endPos;
+ _recheckArea();
+}
+
+void ImageSlider::setEndPos(int x, int y) noexcept
+{
+ setEndPos(Point<int>(x, y));
+}
+
+void ImageSlider::setInverted(bool inverted) noexcept
+{
+ if (fInverted == inverted)
+ return;
+
+ fInverted = inverted;
+ repaint();
+}
+
+void ImageSlider::setDefault(float value) noexcept
+{
+ fValueDef = value;
+ fUsingDefault = true;
+}
+
+void ImageSlider::setRange(float min, float max) noexcept
+{
+ fMinimum = min;
+ fMaximum = max;
+
+ if (fValue < min)
+ {
+ fValue = min;
+ repaint();
+
+ if (fCallback != nullptr && fValueIsSet)
+ {
+ try {
+ fCallback->imageSliderValueChanged(this, fValue);
+ } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange < min");
+ }
+ }
+ else if (fValue > max)
+ {
+ fValue = max;
+ repaint();
+
+ if (fCallback != nullptr && fValueIsSet)
+ {
+ try {
+ fCallback->imageSliderValueChanged(this, fValue);
+ } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange > max");
+ }
+ }
+}
+
+void ImageSlider::setStep(float step) noexcept
+{
+ fStep = step;
+}
+
+void ImageSlider::setCallback(Callback* callback) noexcept
+{
+ fCallback = callback;
+}
+
+void ImageSlider::onDisplay()
+{
+#if 0 // DEBUG, paints slider area
+ glColor3f(0.4f, 0.5f, 0.1f);
+ glRecti(fSliderArea.getX(), fSliderArea.getY(), fSliderArea.getX()+fSliderArea.getWidth(), fSliderArea.getY()+fSliderArea.getHeight());
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+#endif
+
+ const float normValue = (fValue - fMinimum) / (fMaximum - fMinimum);
+
+ int x, y;
+
+ if (fStartPos.getY() == fEndPos.getY())
+ {
+ // horizontal
+ if (fInverted)
+ x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
+ else
+ x = fStartPos.getX() + static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
+
+ y = fStartPos.getY();
+ }
+ else
+ {
+ // vertical
+ x = fStartPos.getX();
+
+ if (fInverted)
+ y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
+ else
+ y = fStartPos.getY() + static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
+ }
+
+ fImage.drawAt(x, y);
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#if 0
+bool ImageSlider::onMouse(const MouseEvent& ev)
+{
+ if (ev.button != 1)
+ return false;
+
+ if (ev.press)
+ {
+ if (! fSliderArea.contains(ev.pos))
+ return false;
+
+ if ((ev.mod & kModifierShift) != 0 && fUsingDefault)
+ {
+ setValue(fValueDef, true);
+ fValueTmp = fValue;
+ return true;
+ }
+
+ float vper;
+ const int x = ev.pos.getX();
+ const int y = ev.pos.getY();
+
+ if (fStartPos.getY() == fEndPos.getY())
+ {
+ // horizontal
+ vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
+ }
+ else
+ {
+ // vertical
+ vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
+ }
+
+ float value;
+
+ if (fInverted)
+ value = fMaximum - vper * (fMaximum - fMinimum);
+ else
+ value = fMinimum + vper * (fMaximum - fMinimum);
+
+ if (value < fMinimum)
+ {
+ fValueTmp = value = fMinimum;
+ }
+ else if (value > fMaximum)
+ {
+ fValueTmp = value = fMaximum;
+ }
+ else if (d_isNotZero(fStep))
+ {
+ fValueTmp = value;
+ const float rest = std::fmod(value, fStep);
+ value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
+ }
+
+ fDragging = true;
+ fStartedX = x;
+ fStartedY = y;
+
+ if (fCallback != nullptr)
+ fCallback->imageSliderDragStarted(this);
+
+ setValue(value, true);
+
+ return true;
+ }
+ else if (fDragging)
+ {
+ if (fCallback != nullptr)
+ fCallback->imageSliderDragFinished(this);
+
+ fDragging = false;
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#if 0
+bool ImageSlider::onMotion(const MotionEvent& ev)
+{
+ if (! fDragging)
+ return false;
+
+ const bool horizontal = fStartPos.getY() == fEndPos.getY();
+ const int x = ev.pos.getX();
+ const int y = ev.pos.getY();
+
+ if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal))
+ {
+ float vper;
+
+ if (horizontal)
+ {
+ // horizontal
+ vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
+ }
+ else
+ {
+ // vertical
+ vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
+ }
+
+ float value;
+
+ if (fInverted)
+ value = fMaximum - vper * (fMaximum - fMinimum);
+ else
+ value = fMinimum + vper * (fMaximum - fMinimum);
+
+ if (value < fMinimum)
+ {
+ fValueTmp = value = fMinimum;
+ }
+ else if (value > fMaximum)
+ {
+ fValueTmp = value = fMaximum;
+ }
+ else if (d_isNotZero(fStep))
+ {
+ fValueTmp = value;
+ const float rest = std::fmod(value, fStep);
+ value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
+ }
+
+ setValue(value, true);
+ }
+ else if (horizontal)
+ {
+ if (x < fSliderArea.getX())
+ setValue(fInverted ? fMaximum : fMinimum, true);
+ else
+ setValue(fInverted ? fMinimum : fMaximum, true);
+ }
+ else
+ {
+ if (y < fSliderArea.getY())
+ setValue(fInverted ? fMaximum : fMinimum, true);
+ else
+ setValue(fInverted ? fMinimum : fMaximum, true);
+ }
+
+ return true;
+}
+
+void ImageSlider::_recheckArea() noexcept
+{
+ if (fStartPos.getY() == fEndPos.getY())
+ {
+ // horizontal
+ fSliderArea = Rectangle<double>(fStartPos.getX(),
+ fStartPos.getY(),
+ fEndPos.getX() + static_cast<int>(fImage.getWidth()) - fStartPos.getX(),
+ static_cast<int>(fImage.getHeight()));
+ }
+ else
+ {
+ // vertical
+ fSliderArea = Rectangle<double>(fStartPos.getX(),
+ fStartPos.getY(),
+ static_cast<int>(fImage.getWidth()),
+ fEndPos.getY() + static_cast<int>(fImage.getHeight()) - fStartPos.getY());
+ }
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
+#if 0
+ImageSwitch::ImageSwitch(Widget* parentWidget, const Image& imageNormal, const Image& imageDown) noexcept
+ : SubWidget(parentWidget),
+ fImageNormal(imageNormal),
+ fImageDown(imageDown),
+ fIsDown(false),
+ fCallback(nullptr)
+{
+ DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());
+
+ setSize(fImageNormal.getSize());
+}
+
+ImageSwitch::ImageSwitch(const ImageSwitch& imageSwitch) noexcept
+ : SubWidget(imageSwitch.getParentWidget()),
+ fImageNormal(imageSwitch.fImageNormal),
+ fImageDown(imageSwitch.fImageDown),
+ fIsDown(imageSwitch.fIsDown),
+ fCallback(imageSwitch.fCallback)
+{
+ DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());
+
+ setSize(fImageNormal.getSize());
+}
+
+ImageSwitch& ImageSwitch::operator=(const ImageSwitch& imageSwitch) noexcept
+{
+ fImageNormal = imageSwitch.fImageNormal;
+ fImageDown = imageSwitch.fImageDown;
+ fIsDown = imageSwitch.fIsDown;
+ fCallback = imageSwitch.fCallback;
+
+ DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());
+
+ setSize(fImageNormal.getSize());
+
+ return *this;
+}
+
+bool ImageSwitch::isDown() const noexcept
+{
+ return fIsDown;
+}
+
+void ImageSwitch::setDown(bool down) noexcept
+{
+ if (fIsDown == down)
+ return;
+
+ fIsDown = down;
+ repaint();
+}
+
+void ImageSwitch::setCallback(Callback* callback) noexcept
+{
+ fCallback = callback;
+}
+
+void ImageSwitch::onDisplay()
+{
+ if (fIsDown)
+ fImageDown.draw();
+ else
+ fImageNormal.draw();
+}
+
+bool ImageSwitch::onMouse(const MouseEvent& ev)
+{
+ if (ev.press && contains(ev.pos))
+ {
+ fIsDown = !fIsDown;
+
+ repaint();
+
+ if (fCallback != nullptr)
+ fCallback->imageSwitchClicked(this, fIsDown);
+
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+// --------------------------------------------------------------------------------------------------------------------
+
END_NAMESPACE_DGL
diff --git a/dgl/src/ImageWidgets.cpp b/dgl/src/ImageWidgets.cpp
@@ -1,876 +0,0 @@
-/*
- * DISTRHO Plugin Framework (DPF)
- * Copyright (C) 2012-2019 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 "../ImageWidgets.hpp"
-#include "WidgetPrivateData.hpp"
-
-// TODO make this code more generic and move GL specific bits to OpenGL.cpp
-#include "../OpenGL.hpp"
-
-// TODO switch to use templated image type after merging widget-related PRs
-#if defined(__GNUC__) && (__GNUC__ >= 6)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-START_NAMESPACE_DGL
-
-// -----------------------------------------------------------------------
-
-ImageKnob::ImageKnob(Widget* const parentWidget, const Image& image, Orientation orientation) noexcept
- : SubWidget(parentWidget),
- fImage(image),
- fMinimum(0.0f),
- fMaximum(1.0f),
- fStep(0.0f),
- fValue(0.5f),
- fValueDef(fValue),
- fValueTmp(fValue),
- fUsingDefault(false),
- fUsingLog(false),
- fOrientation(orientation),
- fRotationAngle(0),
- fDragging(false),
- fLastX(0),
- fLastY(0),
- fCallback(nullptr),
- fIsImgVertical(image.getHeight() > image.getWidth()),
- fImgLayerWidth(fIsImgVertical ? image.getWidth() : image.getHeight()),
- fImgLayerHeight(fImgLayerWidth),
- fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerHeight : image.getWidth()/fImgLayerWidth),
- fIsReady(false),
- fTextureId(0)
-{
- glGenTextures(1, &fTextureId);
- setSize(fImgLayerWidth, fImgLayerHeight);
-}
-
-ImageKnob::ImageKnob(const ImageKnob& imageKnob)
- : SubWidget(imageKnob.getParentWidget()),
- fImage(imageKnob.fImage),
- fMinimum(imageKnob.fMinimum),
- fMaximum(imageKnob.fMaximum),
- fStep(imageKnob.fStep),
- fValue(imageKnob.fValue),
- fValueDef(imageKnob.fValueDef),
- fValueTmp(fValue),
- fUsingDefault(imageKnob.fUsingDefault),
- fUsingLog(imageKnob.fUsingLog),
- fOrientation(imageKnob.fOrientation),
- fRotationAngle(imageKnob.fRotationAngle),
- fDragging(false),
- fLastX(0),
- fLastY(0),
- fCallback(imageKnob.fCallback),
- fIsImgVertical(imageKnob.fIsImgVertical),
- fImgLayerWidth(imageKnob.fImgLayerWidth),
- fImgLayerHeight(imageKnob.fImgLayerHeight),
- fImgLayerCount(imageKnob.fImgLayerCount),
- fIsReady(false),
- fTextureId(0)
-{
- glGenTextures(1, &fTextureId);
- setSize(fImgLayerWidth, fImgLayerHeight);
-}
-
-ImageKnob& ImageKnob::operator=(const ImageKnob& imageKnob)
-{
- fImage = imageKnob.fImage;
- fMinimum = imageKnob.fMinimum;
- fMaximum = imageKnob.fMaximum;
- fStep = imageKnob.fStep;
- fValue = imageKnob.fValue;
- fValueDef = imageKnob.fValueDef;
- fValueTmp = fValue;
- fUsingDefault = imageKnob.fUsingDefault;
- fUsingLog = imageKnob.fUsingLog;
- fOrientation = imageKnob.fOrientation;
- fRotationAngle = imageKnob.fRotationAngle;
- fDragging = false;
- fLastX = 0;
- fLastY = 0;
- fCallback = imageKnob.fCallback;
- fIsImgVertical = imageKnob.fIsImgVertical;
- fImgLayerWidth = imageKnob.fImgLayerWidth;
- fImgLayerHeight = imageKnob.fImgLayerHeight;
- fImgLayerCount = imageKnob.fImgLayerCount;
- fIsReady = false;
-
- if (fTextureId != 0)
- {
- glDeleteTextures(1, &fTextureId);
- fTextureId = 0;
- }
-
- glGenTextures(1, &fTextureId);
- setSize(fImgLayerWidth, fImgLayerHeight);
-
- return *this;
-}
-
-ImageKnob::~ImageKnob()
-{
- if (fTextureId != 0)
- {
- glDeleteTextures(1, &fTextureId);
- fTextureId = 0;
- }
-}
-
-float ImageKnob::getValue() const noexcept
-{
- return fValue;
-}
-
-// NOTE: value is assumed to be scaled if using log
-void ImageKnob::setDefault(float value) noexcept
-{
- fValueDef = value;
- fUsingDefault = true;
-}
-
-void ImageKnob::setRange(float min, float max) noexcept
-{
- DISTRHO_SAFE_ASSERT_RETURN(max > min,);
-
- if (fValue < min)
- {
- fValue = min;
- repaint();
-
- if (fCallback != nullptr)
- {
- try {
- fCallback->imageKnobValueChanged(this, fValue);
- } DISTRHO_SAFE_EXCEPTION("ImageKnob::setRange < min");
- }
- }
- else if (fValue > max)
- {
- fValue = max;
- repaint();
-
- if (fCallback != nullptr)
- {
- try {
- fCallback->imageKnobValueChanged(this, fValue);
- } DISTRHO_SAFE_EXCEPTION("ImageKnob::setRange > max");
- }
- }
-
- fMinimum = min;
- fMaximum = max;
-}
-
-void ImageKnob::setStep(float step) noexcept
-{
- fStep = step;
-}
-
-// NOTE: value is assumed to be scaled if using log
-void ImageKnob::setValue(float value, bool sendCallback) noexcept
-{
- if (d_isEqual(fValue, value))
- return;
-
- fValue = value;
-
- if (d_isZero(fStep))
- fValueTmp = value;
-
- if (fRotationAngle == 0)
- fIsReady = false;
-
- repaint();
-
- if (sendCallback && fCallback != nullptr)
- {
- try {
- fCallback->imageKnobValueChanged(this, fValue);
- } DISTRHO_SAFE_EXCEPTION("ImageKnob::setValue");
- }
-}
-
-void ImageKnob::setUsingLogScale(bool yesNo) noexcept
-{
- fUsingLog = yesNo;
-}
-
-void ImageKnob::setCallback(Callback* callback) noexcept
-{
- fCallback = callback;
-}
-
-void ImageKnob::setOrientation(Orientation orientation) noexcept
-{
- if (fOrientation == orientation)
- return;
-
- fOrientation = orientation;
-}
-
-void ImageKnob::setRotationAngle(int angle)
-{
- if (fRotationAngle == angle)
- return;
-
- fRotationAngle = angle;
- fIsReady = false;
-}
-
-void ImageKnob::setImageLayerCount(uint count) noexcept
-{
- DISTRHO_SAFE_ASSERT_RETURN(count > 1,);
-
- fImgLayerCount = count;
-
- if (fIsImgVertical)
- fImgLayerHeight = fImage.getHeight()/count;
- else
- fImgLayerWidth = fImage.getWidth()/count;
-
- setSize(fImgLayerWidth, fImgLayerHeight);
-}
-
-void ImageKnob::onDisplay()
-{
- const float normValue = ((fUsingLog ? _invlogscale(fValue) : fValue) - fMinimum) / (fMaximum - fMinimum);
-
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, fTextureId);
-
- if (! fIsReady)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-
- static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f };
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans);
-
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- uint imageDataOffset = 0;
-
- if (fRotationAngle == 0)
- {
- DISTRHO_SAFE_ASSERT_RETURN(fImgLayerCount > 0,);
- DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,);
-
- const uint& v1(fIsImgVertical ? fImgLayerWidth : fImgLayerHeight);
- const uint& v2(fIsImgVertical ? fImgLayerHeight : fImgLayerWidth);
-
- const uint layerDataSize = v1 * v2 * ((fImage.getFormat() == kImageFormatBGRA ||
- fImage.getFormat() == kImageFormatRGBA) ? 4 : 3);
- /* */ imageDataOffset = layerDataSize * uint(normValue * float(fImgLayerCount-1));
- }
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
- static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0,
- asOpenGLImageFormat(fImage.getFormat()), GL_UNSIGNED_BYTE, fImage.getRawData() + imageDataOffset);
-
- fIsReady = true;
- }
-
- const int w = static_cast<int>(getWidth());
- const int h = static_cast<int>(getHeight());
-
- if (fRotationAngle != 0)
- {
- glPushMatrix();
-
- const int w2 = w/2;
- const int h2 = h/2;
-
- glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f);
- glRotatef(normValue*static_cast<float>(fRotationAngle), 0.0f, 0.0f, 1.0f);
-
- Rectangle<int>(-w2, -h2, w, h).draw();
-
- glPopMatrix();
- }
- else
- {
- Rectangle<int>(0, 0, w, h).draw();
- }
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_TEXTURE_2D);
-}
-
-bool ImageKnob::onMouse(const MouseEvent& ev)
-{
- if (ev.button != 1)
- return false;
-
- if (ev.press)
- {
- if (! contains(ev.pos))
- return false;
-
- if ((ev.mod & kModifierShift) != 0 && fUsingDefault)
- {
- setValue(fValueDef, true);
- fValueTmp = fValue;
- return true;
- }
-
- fDragging = true;
- fLastX = ev.pos.getX();
- fLastY = ev.pos.getY();
-
- if (fCallback != nullptr)
- fCallback->imageKnobDragStarted(this);
-
- return true;
- }
- else if (fDragging)
- {
- if (fCallback != nullptr)
- fCallback->imageKnobDragFinished(this);
-
- fDragging = false;
- return true;
- }
-
- return false;
-}
-
-bool ImageKnob::onMotion(const MotionEvent& ev)
-{
- if (! fDragging)
- return false;
-
- bool doVal = false;
- float d, value = 0.0f;
-
- if (fOrientation == ImageKnob::Horizontal)
- {
- if (const int movX = ev.pos.getX() - fLastX)
- {
- d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
- value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * float(movX));
- doVal = true;
- }
- }
- else if (fOrientation == ImageKnob::Vertical)
- {
- if (const int movY = fLastY - ev.pos.getY())
- {
- d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
- value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * float(movY));
- doVal = true;
- }
- }
-
- if (! doVal)
- return false;
-
- if (fUsingLog)
- value = _logscale(value);
-
- if (value < fMinimum)
- {
- fValueTmp = value = fMinimum;
- }
- else if (value > fMaximum)
- {
- fValueTmp = value = fMaximum;
- }
- else if (d_isNotZero(fStep))
- {
- fValueTmp = value;
- const float rest = std::fmod(value, fStep);
- value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
- }
-
- setValue(value, true);
-
- fLastX = ev.pos.getX();
- fLastY = ev.pos.getY();
-
- return true;
-}
-
-bool ImageKnob::onScroll(const ScrollEvent& ev)
-{
- if (! contains(ev.pos))
- return false;
-
- const float d = (ev.mod & kModifierControl) ? 2000.0f : 200.0f;
- float value = (fUsingLog ? _invlogscale(fValueTmp) : fValueTmp) + (float(fMaximum - fMinimum) / d * 10.f * ev.delta.getY());
-
- if (fUsingLog)
- value = _logscale(value);
-
- if (value < fMinimum)
- {
- fValueTmp = value = fMinimum;
- }
- else if (value > fMaximum)
- {
- fValueTmp = value = fMaximum;
- }
- else if (d_isNotZero(fStep))
- {
- fValueTmp = value;
- const float rest = std::fmod(value, fStep);
- value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
- }
-
- setValue(value, true);
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-float ImageKnob::_logscale(float value) const
-{
- const float b = std::log(fMaximum/fMinimum)/(fMaximum-fMinimum);
- const float a = fMaximum/std::exp(fMaximum*b);
- return a * std::exp(b*value);
-}
-
-float ImageKnob::_invlogscale(float value) const
-{
- const float b = std::log(fMaximum/fMinimum)/(fMaximum-fMinimum);
- const float a = fMaximum/std::exp(fMaximum*b);
- return std::log(value/a)/b;
-}
-
-// -----------------------------------------------------------------------
-
-ImageSlider::ImageSlider(Widget* const parentWidget, const Image& image) noexcept
- : SubWidget(parentWidget),
- fImage(image),
- fMinimum(0.0f),
- fMaximum(1.0f),
- fStep(0.0f),
- fValue(0.5f),
- fValueDef(fValue),
- fValueTmp(fValue),
- fUsingDefault(false),
- fDragging(false),
- fInverted(false),
- fValueIsSet(false),
- fStartedX(0),
- fStartedY(0),
- fCallback(nullptr),
- fStartPos(),
- fEndPos(),
- fSliderArea()
-{
- setNeedsFullViewportDrawing();
-}
-
-float ImageSlider::getValue() const noexcept
-{
- return fValue;
-}
-
-void ImageSlider::setValue(float value, bool sendCallback) noexcept
-{
- if (! fValueIsSet)
- fValueIsSet = true;
-
- if (d_isEqual(fValue, value))
- return;
-
- fValue = value;
-
- if (d_isZero(fStep))
- fValueTmp = value;
-
- repaint();
-
- if (sendCallback && fCallback != nullptr)
- {
- try {
- fCallback->imageSliderValueChanged(this, fValue);
- } DISTRHO_SAFE_EXCEPTION("ImageSlider::setValue");
- }
-}
-
-void ImageSlider::setStartPos(const Point<int>& startPos) noexcept
-{
- fStartPos = startPos;
- _recheckArea();
-}
-
-void ImageSlider::setStartPos(int x, int y) noexcept
-{
- setStartPos(Point<int>(x, y));
-}
-
-void ImageSlider::setEndPos(const Point<int>& endPos) noexcept
-{
- fEndPos = endPos;
- _recheckArea();
-}
-
-void ImageSlider::setEndPos(int x, int y) noexcept
-{
- setEndPos(Point<int>(x, y));
-}
-
-void ImageSlider::setInverted(bool inverted) noexcept
-{
- if (fInverted == inverted)
- return;
-
- fInverted = inverted;
- repaint();
-}
-
-void ImageSlider::setDefault(float value) noexcept
-{
- fValueDef = value;
- fUsingDefault = true;
-}
-
-void ImageSlider::setRange(float min, float max) noexcept
-{
- fMinimum = min;
- fMaximum = max;
-
- if (fValue < min)
- {
- fValue = min;
- repaint();
-
- if (fCallback != nullptr && fValueIsSet)
- {
- try {
- fCallback->imageSliderValueChanged(this, fValue);
- } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange < min");
- }
- }
- else if (fValue > max)
- {
- fValue = max;
- repaint();
-
- if (fCallback != nullptr && fValueIsSet)
- {
- try {
- fCallback->imageSliderValueChanged(this, fValue);
- } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange > max");
- }
- }
-}
-
-void ImageSlider::setStep(float step) noexcept
-{
- fStep = step;
-}
-
-void ImageSlider::setCallback(Callback* callback) noexcept
-{
- fCallback = callback;
-}
-
-void ImageSlider::onDisplay()
-{
-#if 0 // DEBUG, paints slider area
- glColor3f(0.4f, 0.5f, 0.1f);
- glRecti(fSliderArea.getX(), fSliderArea.getY(), fSliderArea.getX()+fSliderArea.getWidth(), fSliderArea.getY()+fSliderArea.getHeight());
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-#endif
-
- const float normValue = (fValue - fMinimum) / (fMaximum - fMinimum);
-
- int x, y;
-
- if (fStartPos.getY() == fEndPos.getY())
- {
- // horizontal
- if (fInverted)
- x = fEndPos.getX() - static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
- else
- x = fStartPos.getX() + static_cast<int>(normValue*static_cast<float>(fEndPos.getX()-fStartPos.getX()));
-
- y = fStartPos.getY();
- }
- else
- {
- // vertical
- x = fStartPos.getX();
-
- if (fInverted)
- y = fEndPos.getY() - static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
- else
- y = fStartPos.getY() + static_cast<int>(normValue*static_cast<float>(fEndPos.getY()-fStartPos.getY()));
- }
-
- fImage.drawAt(x, y);
-}
-
-bool ImageSlider::onMouse(const MouseEvent& ev)
-{
- if (ev.button != 1)
- return false;
-
- if (ev.press)
- {
- if (! fSliderArea.contains(ev.pos))
- return false;
-
- if ((ev.mod & kModifierShift) != 0 && fUsingDefault)
- {
- setValue(fValueDef, true);
- fValueTmp = fValue;
- return true;
- }
-
- float vper;
- const int x = ev.pos.getX();
- const int y = ev.pos.getY();
-
- if (fStartPos.getY() == fEndPos.getY())
- {
- // horizontal
- vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
- }
- else
- {
- // vertical
- vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
- }
-
- float value;
-
- if (fInverted)
- value = fMaximum - vper * (fMaximum - fMinimum);
- else
- value = fMinimum + vper * (fMaximum - fMinimum);
-
- if (value < fMinimum)
- {
- fValueTmp = value = fMinimum;
- }
- else if (value > fMaximum)
- {
- fValueTmp = value = fMaximum;
- }
- else if (d_isNotZero(fStep))
- {
- fValueTmp = value;
- const float rest = std::fmod(value, fStep);
- value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
- }
-
- fDragging = true;
- fStartedX = x;
- fStartedY = y;
-
- if (fCallback != nullptr)
- fCallback->imageSliderDragStarted(this);
-
- setValue(value, true);
-
- return true;
- }
- else if (fDragging)
- {
- if (fCallback != nullptr)
- fCallback->imageSliderDragFinished(this);
-
- fDragging = false;
- return true;
- }
-
- return false;
-}
-
-bool ImageSlider::onMotion(const MotionEvent& ev)
-{
- if (! fDragging)
- return false;
-
- const bool horizontal = fStartPos.getY() == fEndPos.getY();
- const int x = ev.pos.getX();
- const int y = ev.pos.getY();
-
- if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal))
- {
- float vper;
-
- if (horizontal)
- {
- // horizontal
- vper = float(x - fSliderArea.getX()) / float(fSliderArea.getWidth());
- }
- else
- {
- // vertical
- vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight());
- }
-
- float value;
-
- if (fInverted)
- value = fMaximum - vper * (fMaximum - fMinimum);
- else
- value = fMinimum + vper * (fMaximum - fMinimum);
-
- if (value < fMinimum)
- {
- fValueTmp = value = fMinimum;
- }
- else if (value > fMaximum)
- {
- fValueTmp = value = fMaximum;
- }
- else if (d_isNotZero(fStep))
- {
- fValueTmp = value;
- const float rest = std::fmod(value, fStep);
- value = value - rest + (rest > fStep/2.0f ? fStep : 0.0f);
- }
-
- setValue(value, true);
- }
- else if (horizontal)
- {
- if (x < fSliderArea.getX())
- setValue(fInverted ? fMaximum : fMinimum, true);
- else
- setValue(fInverted ? fMinimum : fMaximum, true);
- }
- else
- {
- if (y < fSliderArea.getY())
- setValue(fInverted ? fMaximum : fMinimum, true);
- else
- setValue(fInverted ? fMinimum : fMaximum, true);
- }
-
- return true;
-}
-
-void ImageSlider::_recheckArea() noexcept
-{
- if (fStartPos.getY() == fEndPos.getY())
- {
- // horizontal
- fSliderArea = Rectangle<double>(fStartPos.getX(),
- fStartPos.getY(),
- fEndPos.getX() + static_cast<int>(fImage.getWidth()) - fStartPos.getX(),
- static_cast<int>(fImage.getHeight()));
- }
- else
- {
- // vertical
- fSliderArea = Rectangle<double>(fStartPos.getX(),
- fStartPos.getY(),
- static_cast<int>(fImage.getWidth()),
- fEndPos.getY() + static_cast<int>(fImage.getHeight()) - fStartPos.getY());
- }
-}
-
-// -----------------------------------------------------------------------
-
-ImageSwitch::ImageSwitch(Widget* parentWidget, const Image& imageNormal, const Image& imageDown) noexcept
- : SubWidget(parentWidget),
- fImageNormal(imageNormal),
- fImageDown(imageDown),
- fIsDown(false),
- fCallback(nullptr)
-{
- DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());
-
- setSize(fImageNormal.getSize());
-}
-
-ImageSwitch::ImageSwitch(const ImageSwitch& imageSwitch) noexcept
- : SubWidget(imageSwitch.getParentWidget()),
- fImageNormal(imageSwitch.fImageNormal),
- fImageDown(imageSwitch.fImageDown),
- fIsDown(imageSwitch.fIsDown),
- fCallback(imageSwitch.fCallback)
-{
- DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());
-
- setSize(fImageNormal.getSize());
-}
-
-ImageSwitch& ImageSwitch::operator=(const ImageSwitch& imageSwitch) noexcept
-{
- fImageNormal = imageSwitch.fImageNormal;
- fImageDown = imageSwitch.fImageDown;
- fIsDown = imageSwitch.fIsDown;
- fCallback = imageSwitch.fCallback;
-
- DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize());
-
- setSize(fImageNormal.getSize());
-
- return *this;
-}
-
-bool ImageSwitch::isDown() const noexcept
-{
- return fIsDown;
-}
-
-void ImageSwitch::setDown(bool down) noexcept
-{
- if (fIsDown == down)
- return;
-
- fIsDown = down;
- repaint();
-}
-
-void ImageSwitch::setCallback(Callback* callback) noexcept
-{
- fCallback = callback;
-}
-
-void ImageSwitch::onDisplay()
-{
- if (fIsDown)
- fImageDown.draw();
- else
- fImageNormal.draw();
-}
-
-bool ImageSwitch::onMouse(const MouseEvent& ev)
-{
- if (ev.press && contains(ev.pos))
- {
- fIsDown = !fIsDown;
-
- repaint();
-
- if (fCallback != nullptr)
- fCallback->imageSwitchClicked(this, fIsDown);
-
- return true;
- }
-
- return false;
-}
-
-// -----------------------------------------------------------------------
-
-END_NAMESPACE_DGL
-
-#if defined(__GNUC__) && (__GNUC__ >= 6)
-# pragma GCC diagnostic pop
-#endif