Browse Source

Move Image Widgets implementation into a single file

pull/6/head
falkTX 8 years ago
parent
commit
5171f69a21
8 changed files with 1187 additions and 1286 deletions
  1. +0
    -1
      dgl/ImageWidgets.hpp
  2. +1
    -5
      dgl/Makefile
  3. +0
    -89
      dgl/src/ImageAboutWindow.cpp
  4. +0
    -190
      dgl/src/ImageButton.cpp
  5. +0
    -480
      dgl/src/ImageKnob.cpp
  6. +0
    -399
      dgl/src/ImageSlider.cpp
  7. +0
    -122
      dgl/src/ImageSwitch.cpp
  8. +1186
    -0
      dgl/src/ImageWidgets.cpp

+ 0
- 1
dgl/ImageWidgets.hpp View File

@@ -43,7 +43,6 @@ protected:
private:
Image fImgBackground;

//DISTRHO_DECLARE_NON_COPY_CLASS(ImageAboutWindow)
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageAboutWindow)
};



+ 1
- 5
dgl/Makefile View File

@@ -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



+ 0
- 89
dgl/src/ImageAboutWindow.cpp View File

@@ -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

+ 0
- 190
dgl/src/ImageButton.cpp View File

@@ -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

+ 0
- 480
dgl/src/ImageKnob.cpp View File

@@ -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

+ 0
- 399
dgl/src/ImageSlider.cpp View File

@@ -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

+ 0
- 122
dgl/src/ImageSwitch.cpp View File

@@ -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

+ 1186
- 0
dgl/src/ImageWidgets.cpp
File diff suppressed because it is too large
View File


Loading…
Cancel
Save