| @@ -43,7 +43,6 @@ protected: | |||
| private: | |||
| Image fImgBackground; | |||
| //DISTRHO_DECLARE_NON_COPY_CLASS(ImageAboutWindow) | |||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow) | |||
| }; | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||