DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 5171f69a2129f87ae3803ce7c2ee2c813a949221
parent 8f99465b717e816cb301548d7d3790de56c9ec28
Author: falkTX <falktx@gmail.com>
Date:   Tue,  5 May 2015 01:27:13 +0200

Move Image Widgets implementation into a single file

Diffstat:
Mdgl/ImageWidgets.hpp | 1-
Mdgl/Makefile | 6+-----
Ddgl/src/ImageAboutWindow.cpp | 89-------------------------------------------------------------------------------
Ddgl/src/ImageButton.cpp | 190-------------------------------------------------------------------------------
Ddgl/src/ImageKnob.cpp | 480-------------------------------------------------------------------------------
Ddgl/src/ImageSlider.cpp | 399-------------------------------------------------------------------------------
Ddgl/src/ImageSwitch.cpp | 122-------------------------------------------------------------------------------
Adgl/src/ImageWidgets.cpp | 1186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 1187 insertions(+), 1286 deletions(-)

diff --git a/dgl/ImageWidgets.hpp b/dgl/ImageWidgets.hpp @@ -43,7 +43,6 @@ protected: private: Image fImgBackground; - //DISTRHO_DECLARE_NON_COPY_CLASS(ImageAboutWindow) DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow) }; diff --git a/dgl/Makefile b/dgl/Makefile @@ -19,11 +19,7 @@ OBJS = \ src/Color.cpp.o \ src/Geometry.cpp.o \ src/Image.cpp.o \ - src/ImageAboutWindow.cpp.o \ - src/ImageButton.cpp.o \ - src/ImageKnob.cpp.o \ - src/ImageSlider.cpp.o \ - src/ImageSwitch.cpp.o \ + src/ImageWidgets.cpp.o \ src/NanoVG.cpp.o \ src/Widget.cpp.o diff --git a/dgl/src/ImageAboutWindow.cpp b/dgl/src/ImageAboutWindow.cpp @@ -1,89 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2015 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" - -START_NAMESPACE_DGL - -// ----------------------------------------------------------------------- - -ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image) - : Window(parent.getApp(), parent), - Widget((Window&)*this), - fImgBackground(image)/*, - leakDetector_ImageAboutWindow()*/ -{ - Window::setResizable(false); - Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight())); - Window::setTitle("About"); -} - -ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image) - : Window(widget->getParentApp(), widget->getParentWindow()), - Widget((Window&)*this), - fImgBackground(image)/*, - leakDetector_ImageAboutWindow()*/ -{ - Window::setResizable(false); - Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight())); - Window::setTitle("About"); -} - -void ImageAboutWindow::setImage(const Image& image) -{ - if (fImgBackground == image) - return; - - fImgBackground = image; - Window::setSize(static_cast<uint>(image.getWidth()), static_cast<uint>(image.getHeight())); -} - -void ImageAboutWindow::onDisplay() -{ - fImgBackground.draw(); -} - -bool ImageAboutWindow::onKeyboard(const KeyboardEvent& ev) -{ - if (ev.press && ev.key == CHAR_ESCAPE) - { - Window::close(); - return true; - } - - return false; -} - -bool ImageAboutWindow::onMouse(const MouseEvent& ev) -{ - if (ev.press) - { - Window::close(); - return true; - } - - return false; -} - -void ImageAboutWindow::onReshape(uint width, uint height) -{ - Widget::setSize(width, height); - Window::onReshape(width, height); -} - -// ----------------------------------------------------------------------- - -END_NAMESPACE_DGL diff --git a/dgl/src/ImageButton.cpp b/dgl/src/ImageButton.cpp @@ -1,190 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2015 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" - -START_NAMESPACE_DGL - -// ----------------------------------------------------------------------- - -ImageButton::ImageButton(Window& parent, const Image& image) noexcept - : Widget(parent), - fImageNormal(image), - fImageHover(image), - fImageDown(image), - fCurImage(&fImageNormal), - fCurButton(-1), - fCallback(nullptr), - leakDetector_ImageButton() {} - -ImageButton::ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept - : Widget(parent), - fImageNormal(imageNormal), - fImageHover(imageHover), - fImageDown(imageDown), - fCurImage(&fImageNormal), - fCurButton(-1), - fCallback(nullptr), - leakDetector_ImageButton() -{ - DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); - - setSize(fCurImage->getSize()); -} - -ImageButton::ImageButton(Widget* widget, const Image& image) noexcept - : Widget(widget->getParentWindow()), - fImageNormal(image), - fImageHover(image), - fImageDown(image), - fCurImage(&fImageNormal), - fCurButton(-1), - fCallback(nullptr), - leakDetector_ImageButton() {} - -ImageButton::ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept - : Widget(widget->getParentWindow()), - fImageNormal(imageNormal), - fImageHover(imageHover), - fImageDown(imageDown), - fCurImage(&fImageNormal), - fCurButton(-1), - fCallback(nullptr), - leakDetector_ImageButton() -{ - DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); - - setSize(fCurImage->getSize()); -} - -ImageButton::ImageButton(const ImageButton& imageButton) noexcept - : Widget(imageButton.getParentWindow()), - fImageNormal(imageButton.fImageNormal), - fImageHover(imageButton.fImageHover), - fImageDown(imageButton.fImageDown), - fCurImage(&fImageNormal), - fCurButton(-1), - fCallback(imageButton.fCallback), - leakDetector_ImageButton() -{ - DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); - - setSize(fCurImage->getSize()); -} - -ImageButton& ImageButton::operator=(const ImageButton& imageButton) noexcept -{ - fImageNormal = imageButton.fImageNormal; - fImageHover = imageButton.fImageHover; - fImageDown = imageButton.fImageDown; - fCurImage = &fImageNormal; - fCurButton = -1; - fCallback = imageButton.fCallback; - - DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); - - setSize(fCurImage->getSize()); - - return *this; -} - -void ImageButton::setCallback(Callback* callback) noexcept -{ - fCallback = callback; -} - -void ImageButton::onDisplay() -{ - fCurImage->draw(); -} - -bool ImageButton::onMouse(const MouseEvent& ev) -{ - if (fCurButton != -1 && ! ev.press) - { - if (fCurImage != &fImageNormal) - { - fCurImage = &fImageNormal; - repaint(); - } - - if (! contains(ev.pos)) - { - fCurButton = -1; - return false; - } - - if (fCallback != nullptr) - fCallback->imageButtonClicked(this, fCurButton); - -#if 0 - if (contains(ev.pos)) - { - fCurImage = &fImageHover; - repaint(); - } -#endif - - fCurButton = -1; - - return true; - } - - if (ev.press && contains(ev.pos)) - { - if (fCurImage != &fImageDown) - { - fCurImage = &fImageDown; - repaint(); - } - - fCurButton = ev.button; - return true; - } - - return false; -} - -bool ImageButton::onMotion(const MotionEvent& ev) -{ - if (fCurButton != -1) - return true; - - if (contains(ev.pos)) - { - if (fCurImage != &fImageHover) - { - fCurImage = &fImageHover; - repaint(); - } - - return true; - } - else - { - if (fCurImage != &fImageNormal) - { - fCurImage = &fImageNormal; - repaint(); - } - - return false; - } -} - -// ----------------------------------------------------------------------- - -END_NAMESPACE_DGL diff --git a/dgl/src/ImageKnob.cpp b/dgl/src/ImageKnob.cpp @@ -1,480 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2015 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 <cmath> - -START_NAMESPACE_DGL - -// ----------------------------------------------------------------------- - -ImageKnob::ImageKnob(Window& parent, const Image& image, Orientation orientation) noexcept - : Widget(parent), - 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), - leakDetector_ImageKnob() -{ - glGenTextures(1, &fTextureId); - setSize(fImgLayerWidth, fImgLayerHeight); -} - -ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation) noexcept - : Widget(widget->getParentWindow()), - 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), - leakDetector_ImageKnob() -{ - glGenTextures(1, &fTextureId); - setSize(fImgLayerWidth, fImgLayerHeight); -} - -ImageKnob::ImageKnob(const ImageKnob& imageKnob) - : Widget(imageKnob.getParentWindow()), - 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), - leakDetector_ImageKnob() -{ - 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() == GL_BGRA || fImage.getFormat() == GL_RGBA) ? 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, - fImage.getFormat(), fImage.getType(), 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 & MODIFIER_SHIFT) != 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 & MODIFIER_CTRL) ? 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 & MODIFIER_CTRL) ? 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 & MODIFIER_CTRL) ? 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; -} - -// ----------------------------------------------------------------------- - -END_NAMESPACE_DGL diff --git a/dgl/src/ImageSlider.cpp b/dgl/src/ImageSlider.cpp @@ -1,399 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2015 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 <cmath> - -START_NAMESPACE_DGL - -// ----------------------------------------------------------------------- - -ImageSlider::ImageSlider(Window& parent, const Image& image) noexcept - : Widget(parent), - fImage(image), - fMinimum(0.0f), - fMaximum(1.0f), - fStep(0.0f), - fValue(0.5f), - fValueTmp(fValue), - fDragging(false), - fInverted(false), - fStartedX(0), - fStartedY(0), - fCallback(nullptr), - fStartPos(), - fEndPos(), - fSliderArea(), - leakDetector_ImageSlider() -{ - fNeedsFullViewport = true; -} - -ImageSlider::ImageSlider(Widget* widget, const Image& image) noexcept - : Widget(widget->getParentWindow()), - fImage(image), - fMinimum(0.0f), - fMaximum(1.0f), - fStep(0.0f), - fValue(0.5f), - fValueTmp(fValue), - fDragging(false), - fInverted(false), - fStartedX(0), - fStartedY(0), - fCallback(nullptr), - fStartPos(), - fEndPos(), - fSliderArea(), - leakDetector_ImageSlider() -{ - fNeedsFullViewport = true; -} - -ImageSlider::ImageSlider(const ImageSlider& imageSlider) noexcept - : Widget(imageSlider.getParentWindow()), - fImage(imageSlider.fImage), - fMinimum(imageSlider.fMinimum), - fMaximum(imageSlider.fMaximum), - fStep(imageSlider.fStep), - fValue(imageSlider.fValue), - fValueTmp(fValue), - fDragging(false), - fInverted(imageSlider.fInverted), - fStartedX(0), - fStartedY(0), - fCallback(imageSlider.fCallback), - fStartPos(imageSlider.fStartPos), - fEndPos(imageSlider.fEndPos), - fSliderArea(imageSlider.fSliderArea), - leakDetector_ImageSlider() -{ - fNeedsFullViewport = true; -} - -ImageSlider& ImageSlider::operator=(const ImageSlider& imageSlider) noexcept -{ - fImage = imageSlider.fImage; - fMinimum = imageSlider.fMinimum; - fMaximum = imageSlider.fMaximum; - fStep = imageSlider.fStep; - fValue = imageSlider.fValue; - fValueTmp = fValue; - fDragging = false; - fInverted = imageSlider.fInverted; - fStartedX = 0; - fStartedY = 0; - fCallback = imageSlider.fCallback; - fStartPos = imageSlider.fStartPos; - fEndPos = imageSlider.fEndPos; - fSliderArea = imageSlider.fSliderArea; - - return *this; -} - -float ImageSlider::getValue() const noexcept -{ - return fValue; -} - -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::setRange(float min, float max) noexcept -{ - if (fValue < min) - { - fValue = min; - repaint(); - - if (fCallback != nullptr) - { - try { - fCallback->imageSliderValueChanged(this, fValue); - } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange < min"); - } - } - else if (fValue > max) - { - fValue = max; - repaint(); - - if (fCallback != nullptr) - { - try { - fCallback->imageSliderValueChanged(this, fValue); - } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange > max"); - } - } - - fMinimum = min; - fMaximum = max; -} - -void ImageSlider::setStep(float step) noexcept -{ - fStep = step; -} - -void ImageSlider::setValue(float value, bool sendCallback) noexcept -{ - 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::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; - - 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<int>(fStartPos.getX(), - fStartPos.getY(), - fEndPos.getX() + static_cast<int>(fImage.getWidth()) - fStartPos.getX(), - static_cast<int>(fImage.getHeight())); - } - else - { - // vertical - fSliderArea = Rectangle<int>(fStartPos.getX(), - fStartPos.getY(), - static_cast<int>(fImage.getWidth()), - fEndPos.getY() + static_cast<int>(fImage.getHeight()) - fStartPos.getY()); - } -} - -// ----------------------------------------------------------------------- - -END_NAMESPACE_DGL diff --git a/dgl/src/ImageSwitch.cpp b/dgl/src/ImageSwitch.cpp @@ -1,122 +0,0 @@ -/* - * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2015 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" - -START_NAMESPACE_DGL - -// ----------------------------------------------------------------------- - -ImageSwitch::ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown) noexcept - : Widget(parent), - fImageNormal(imageNormal), - fImageDown(imageDown), - fIsDown(false), - fCallback(nullptr), - leakDetector_ImageSwitch() -{ - DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); - - setSize(fImageNormal.getSize()); -} - -ImageSwitch::ImageSwitch(Widget* widget, const Image& imageNormal, const Image& imageDown) noexcept - : Widget(widget->getParentWindow()), - fImageNormal(imageNormal), - fImageDown(imageDown), - fIsDown(false), - fCallback(nullptr), - leakDetector_ImageSwitch() -{ - DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); - - setSize(fImageNormal.getSize()); -} - -ImageSwitch::ImageSwitch(const ImageSwitch& imageSwitch) noexcept - : Widget(imageSwitch.getParentWindow()), - fImageNormal(imageSwitch.fImageNormal), - fImageDown(imageSwitch.fImageDown), - fIsDown(imageSwitch.fIsDown), - fCallback(imageSwitch.fCallback), - leakDetector_ImageSwitch() -{ - 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 diff --git a/dgl/src/ImageWidgets.cpp b/dgl/src/ImageWidgets.cpp @@ -0,0 +1,1186 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2015 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 <cmath> + +START_NAMESPACE_DGL + +// ----------------------------------------------------------------------- + +ImageAboutWindow::ImageAboutWindow(Window& parent, const Image& image) + : Window(parent.getApp(), parent), + Widget((Window&)*this), + fImgBackground(image), + leakDetector_ImageAboutWindow() +{ + Window::setResizable(false); + Window::setSize(image.getSize()); + Window::setTitle("About"); +} + +ImageAboutWindow::ImageAboutWindow(Widget* widget, const Image& image) + : Window(widget->getParentApp(), widget->getParentWindow()), + Widget((Window&)*this), + fImgBackground(image), + leakDetector_ImageAboutWindow() +{ + Window::setResizable(false); + Window::setSize(image.getSize()); + Window::setTitle("About"); +} + +void ImageAboutWindow::setImage(const Image& image) +{ + if (fImgBackground == image) + return; + + fImgBackground = image; + Window::setSize(image.getSize()); +} + +void ImageAboutWindow::onDisplay() +{ + fImgBackground.draw(); +} + +bool ImageAboutWindow::onKeyboard(const KeyboardEvent& ev) +{ + if (ev.press && ev.key == CHAR_ESCAPE) + { + Window::close(); + return true; + } + + return false; +} + +bool ImageAboutWindow::onMouse(const MouseEvent& ev) +{ + if (ev.press) + { + Window::close(); + return true; + } + + return false; +} + +void ImageAboutWindow::onReshape(uint width, uint height) +{ + Widget::setSize(width, height); + Window::onReshape(width, height); +} + +// ----------------------------------------------------------------------- + +ImageButton::ImageButton(Window& parent, const Image& image) noexcept + : Widget(parent), + fImageNormal(image), + fImageHover(image), + fImageDown(image), + fCurImage(&fImageNormal), + fCurButton(-1), + fCallback(nullptr), + leakDetector_ImageButton() {} + +ImageButton::ImageButton(Window& parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept + : Widget(parent), + fImageNormal(imageNormal), + fImageHover(imageHover), + fImageDown(imageDown), + fCurImage(&fImageNormal), + fCurButton(-1), + fCallback(nullptr), + leakDetector_ImageButton() +{ + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); + + setSize(fCurImage->getSize()); +} + +ImageButton::ImageButton(Widget* widget, const Image& image) noexcept + : Widget(widget->getParentWindow()), + fImageNormal(image), + fImageHover(image), + fImageDown(image), + fCurImage(&fImageNormal), + fCurButton(-1), + fCallback(nullptr), + leakDetector_ImageButton() {} + +ImageButton::ImageButton(Widget* widget, const Image& imageNormal, const Image& imageHover, const Image& imageDown) noexcept + : Widget(widget->getParentWindow()), + fImageNormal(imageNormal), + fImageHover(imageHover), + fImageDown(imageDown), + fCurImage(&fImageNormal), + fCurButton(-1), + fCallback(nullptr), + leakDetector_ImageButton() +{ + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); + + setSize(fCurImage->getSize()); +} + +ImageButton::ImageButton(const ImageButton& imageButton) noexcept + : Widget(imageButton.getParentWindow()), + fImageNormal(imageButton.fImageNormal), + fImageHover(imageButton.fImageHover), + fImageDown(imageButton.fImageDown), + fCurImage(&fImageNormal), + fCurButton(-1), + fCallback(imageButton.fCallback), + leakDetector_ImageButton() +{ + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); + + setSize(fCurImage->getSize()); +} + +ImageButton& ImageButton::operator=(const ImageButton& imageButton) noexcept +{ + fImageNormal = imageButton.fImageNormal; + fImageHover = imageButton.fImageHover; + fImageDown = imageButton.fImageDown; + fCurImage = &fImageNormal; + fCurButton = -1; + fCallback = imageButton.fCallback; + + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); + + setSize(fCurImage->getSize()); + + return *this; +} + +void ImageButton::setCallback(Callback* callback) noexcept +{ + fCallback = callback; +} + +void ImageButton::onDisplay() +{ + fCurImage->draw(); +} + +bool ImageButton::onMouse(const MouseEvent& ev) +{ + if (fCurButton != -1 && ! ev.press) + { + if (fCurImage != &fImageNormal) + { + fCurImage = &fImageNormal; + repaint(); + } + + if (! contains(ev.pos)) + { + fCurButton = -1; + return false; + } + + if (fCallback != nullptr) + fCallback->imageButtonClicked(this, fCurButton); + +#if 0 + if (contains(ev.pos)) + { + fCurImage = &fImageHover; + repaint(); + } +#endif + + fCurButton = -1; + + return true; + } + + if (ev.press && contains(ev.pos)) + { + if (fCurImage != &fImageDown) + { + fCurImage = &fImageDown; + repaint(); + } + + fCurButton = ev.button; + return true; + } + + return false; +} + +bool ImageButton::onMotion(const MotionEvent& ev) +{ + if (fCurButton != -1) + return true; + + if (contains(ev.pos)) + { + if (fCurImage != &fImageHover) + { + fCurImage = &fImageHover; + repaint(); + } + + return true; + } + else + { + if (fCurImage != &fImageNormal) + { + fCurImage = &fImageNormal; + repaint(); + } + + return false; + } +} + +// ----------------------------------------------------------------------- + +ImageKnob::ImageKnob(Window& parent, const Image& image, Orientation orientation) noexcept + : Widget(parent), + 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), + leakDetector_ImageKnob() +{ + glGenTextures(1, &fTextureId); + setSize(fImgLayerWidth, fImgLayerHeight); +} + +ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation) noexcept + : Widget(widget->getParentWindow()), + 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), + leakDetector_ImageKnob() +{ + glGenTextures(1, &fTextureId); + setSize(fImgLayerWidth, fImgLayerHeight); +} + +ImageKnob::ImageKnob(const ImageKnob& imageKnob) + : Widget(imageKnob.getParentWindow()), + 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), + leakDetector_ImageKnob() +{ + 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() == GL_BGRA || fImage.getFormat() == GL_RGBA) ? 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, + fImage.getFormat(), fImage.getType(), 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 & MODIFIER_SHIFT) != 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 & MODIFIER_CTRL) ? 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 & MODIFIER_CTRL) ? 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 & MODIFIER_CTRL) ? 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(Window& parent, const Image& image) noexcept + : Widget(parent), + fImage(image), + fMinimum(0.0f), + fMaximum(1.0f), + fStep(0.0f), + fValue(0.5f), + fValueTmp(fValue), + fDragging(false), + fInverted(false), + fStartedX(0), + fStartedY(0), + fCallback(nullptr), + fStartPos(), + fEndPos(), + fSliderArea(), + leakDetector_ImageSlider() +{ + fNeedsFullViewport = true; +} + +ImageSlider::ImageSlider(Widget* widget, const Image& image) noexcept + : Widget(widget->getParentWindow()), + fImage(image), + fMinimum(0.0f), + fMaximum(1.0f), + fStep(0.0f), + fValue(0.5f), + fValueTmp(fValue), + fDragging(false), + fInverted(false), + fStartedX(0), + fStartedY(0), + fCallback(nullptr), + fStartPos(), + fEndPos(), + fSliderArea(), + leakDetector_ImageSlider() +{ + fNeedsFullViewport = true; +} + +ImageSlider::ImageSlider(const ImageSlider& imageSlider) noexcept + : Widget(imageSlider.getParentWindow()), + fImage(imageSlider.fImage), + fMinimum(imageSlider.fMinimum), + fMaximum(imageSlider.fMaximum), + fStep(imageSlider.fStep), + fValue(imageSlider.fValue), + fValueTmp(fValue), + fDragging(false), + fInverted(imageSlider.fInverted), + fStartedX(0), + fStartedY(0), + fCallback(imageSlider.fCallback), + fStartPos(imageSlider.fStartPos), + fEndPos(imageSlider.fEndPos), + fSliderArea(imageSlider.fSliderArea), + leakDetector_ImageSlider() +{ + fNeedsFullViewport = true; +} + +ImageSlider& ImageSlider::operator=(const ImageSlider& imageSlider) noexcept +{ + fImage = imageSlider.fImage; + fMinimum = imageSlider.fMinimum; + fMaximum = imageSlider.fMaximum; + fStep = imageSlider.fStep; + fValue = imageSlider.fValue; + fValueTmp = fValue; + fDragging = false; + fInverted = imageSlider.fInverted; + fStartedX = 0; + fStartedY = 0; + fCallback = imageSlider.fCallback; + fStartPos = imageSlider.fStartPos; + fEndPos = imageSlider.fEndPos; + fSliderArea = imageSlider.fSliderArea; + + return *this; +} + +float ImageSlider::getValue() const noexcept +{ + return fValue; +} + +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::setRange(float min, float max) noexcept +{ + if (fValue < min) + { + fValue = min; + repaint(); + + if (fCallback != nullptr) + { + try { + fCallback->imageSliderValueChanged(this, fValue); + } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange < min"); + } + } + else if (fValue > max) + { + fValue = max; + repaint(); + + if (fCallback != nullptr) + { + try { + fCallback->imageSliderValueChanged(this, fValue); + } DISTRHO_SAFE_EXCEPTION("ImageSlider::setRange > max"); + } + } + + fMinimum = min; + fMaximum = max; +} + +void ImageSlider::setStep(float step) noexcept +{ + fStep = step; +} + +void ImageSlider::setValue(float value, bool sendCallback) noexcept +{ + 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::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; + + 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<int>(fStartPos.getX(), + fStartPos.getY(), + fEndPos.getX() + static_cast<int>(fImage.getWidth()) - fStartPos.getX(), + static_cast<int>(fImage.getHeight())); + } + else + { + // vertical + fSliderArea = Rectangle<int>(fStartPos.getX(), + fStartPos.getY(), + static_cast<int>(fImage.getWidth()), + fEndPos.getY() + static_cast<int>(fImage.getHeight()) - fStartPos.getY()); + } +} + +// ----------------------------------------------------------------------- + +ImageSwitch::ImageSwitch(Window& parent, const Image& imageNormal, const Image& imageDown) noexcept + : Widget(parent), + fImageNormal(imageNormal), + fImageDown(imageDown), + fIsDown(false), + fCallback(nullptr), + leakDetector_ImageSwitch() +{ + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); + + setSize(fImageNormal.getSize()); +} + +ImageSwitch::ImageSwitch(Widget* widget, const Image& imageNormal, const Image& imageDown) noexcept + : Widget(widget->getParentWindow()), + fImageNormal(imageNormal), + fImageDown(imageDown), + fIsDown(false), + fCallback(nullptr), + leakDetector_ImageSwitch() +{ + DISTRHO_SAFE_ASSERT(fImageNormal.getSize() == fImageDown.getSize()); + + setSize(fImageNormal.getSize()); +} + +ImageSwitch::ImageSwitch(const ImageSwitch& imageSwitch) noexcept + : Widget(imageSwitch.getParentWindow()), + fImageNormal(imageSwitch.fImageNormal), + fImageDown(imageSwitch.fImageDown), + fIsDown(imageSwitch.fIsDown), + fCallback(imageSwitch.fCallback), + leakDetector_ImageSwitch() +{ + 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