Browse Source

Start of common event handlers, split off button as a start

Signed-off-by: falkTX <falktx@falktx.com>
pull/292/head
falkTX 4 years ago
parent
commit
2fe6b274d1
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
7 changed files with 346 additions and 118 deletions
  1. +1
    -0
      cmake/DPF-plugin.cmake
  2. +77
    -0
      dgl/EventHandlers.hpp
  3. +3
    -1
      dgl/ImageBaseWidgets.hpp
  4. +1
    -1
      dgl/Makefile
  5. +0
    -97
      dgl/src/Common.hpp
  6. +232
    -0
      dgl/src/EventHandlers.cpp
  7. +32
    -19
      dgl/src/ImageBaseWidgets.cpp

+ 1
- 0
cmake/DPF-plugin.cmake View File

@@ -326,6 +326,7 @@ function(dpf__add_dgl_cairo)
"${DPF_ROOT_DIR}/dgl/src/Application.cpp"
"${DPF_ROOT_DIR}/dgl/src/ApplicationPrivateData.cpp"
"${DPF_ROOT_DIR}/dgl/src/Color.cpp"
"${DPF_ROOT_DIR}/dgl/src/EventHandlers.cpp"
"${DPF_ROOT_DIR}/dgl/src/Geometry.cpp"
"${DPF_ROOT_DIR}/dgl/src/ImageBase.cpp"
"${DPF_ROOT_DIR}/dgl/src/ImageBaseWidgets.cpp"


+ 77
- 0
dgl/EventHandlers.hpp View File

@@ -0,0 +1,77 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef DGL_EVENT_HANDLERS_HPP_INCLUDED
#define DGL_EVENT_HANDLERS_HPP_INCLUDED

#include "Widget.hpp"

START_NAMESPACE_DGL

// --------------------------------------------------------------------------------------------------------------------

class ButtonEventHandler
{
public:
enum State {
kButtonStateDefault = 0x0,
kButtonStateHover = 0x1,
kButtonStateActive = 0x2,
kButtonStateActiveHover = kButtonStateActive|kButtonStateHover
};

class Callback
{
public:
virtual ~Callback() {}
virtual void buttonClicked(SubWidget* widget, int button) = 0;
};

explicit ButtonEventHandler(SubWidget* self);
~ButtonEventHandler();

bool isActive() noexcept;
void setActive(bool active, bool sendCallback) noexcept;

bool isChecked() const noexcept;
void setChecked(bool checked, bool sendCallback) noexcept;

bool isCheckable() const noexcept;
void setCheckable(bool checkable) noexcept;

void setCallback(Callback* callback) noexcept;

protected:
State getState() const noexcept;

virtual void stateChanged(State state, State oldState);

bool mouseEvent(const Widget::MouseEvent& ev);
bool motionEvent(const Widget::MotionEvent& ev);

private:
struct PrivateData;
PrivateData* const pData;

DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ButtonEventHandler)
};

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DGL

#endif // DGL_EVENT_HANDLERS_HPP_INCLUDED


+ 3
- 1
dgl/ImageBaseWidgets.hpp View File

@@ -17,6 +17,7 @@
#ifndef DGL_IMAGE_BASE_WIDGETS_HPP_INCLUDED
#define DGL_IMAGE_BASE_WIDGETS_HPP_INCLUDED

#include "EventHandlers.hpp"
#include "StandaloneWindow.hpp"
#include "SubWidget.hpp"

@@ -47,7 +48,8 @@ private:
// --------------------------------------------------------------------------------------------------------------------

template <class ImageType>
class ImageBaseButton : public SubWidget
class ImageBaseButton : public SubWidget,
public ButtonEventHandler
{
public:
class Callback


+ 1
- 1
dgl/Makefile View File

@@ -27,6 +27,7 @@ OBJS_common = \
../build/dgl/Application.cpp.o \
../build/dgl/ApplicationPrivateData.cpp.o \
../build/dgl/Color.cpp.o \
../build/dgl/EventHandlers.cpp.o \
../build/dgl/Geometry.cpp.o \
../build/dgl/ImageBase.cpp.o \
../build/dgl/ImageBaseWidgets.cpp.o \
@@ -39,7 +40,6 @@ OBJS_common = \
../build/dgl/WidgetPrivateData.cpp.o \
../build/dgl/Window.cpp.o \
../build/dgl/WindowPrivateData.cpp.o
# ../build/dgl/WindowFileBrowser.cpp.o

# ---------------------------------------------------------------------------------------------------------------------



+ 0
- 97
dgl/src/Common.hpp View File

@@ -23,103 +23,6 @@ START_NAMESPACE_DGL

// -----------------------------------------------------------------------

template <class ImageType>
struct ButtonImpl {
enum State {
kStateNormal = 0,
kStateHover,
kStateDown
};

int button;
int state;
ImageBaseButton<ImageType>* const self;

typename ImageBaseButton<ImageType>::Callback* callback_img;

explicit ButtonImpl(ImageBaseButton<ImageType>* const s) noexcept
: button(-1),
state(kStateNormal),
self(s),
callback_img(nullptr) {}

bool onMouse(const Widget::MouseEvent& ev)
{
// button was released, handle it now
if (button != -1 && ! ev.press)
{
DISTRHO_SAFE_ASSERT(state == kStateDown);

// release button
const int button2 = button;
button = -1;

// cursor was moved outside the button bounds, ignore click
if (! self->contains(ev.pos))
{
state = kStateNormal;
self->repaint();
return true;
}

// still on bounds, register click
state = kStateHover;
self->repaint();

if (callback_img != nullptr)
callback_img->imageButtonClicked(self, button2);

return true;
}

// button was pressed, wait for release
if (ev.press && self->contains(ev.pos))
{
button = static_cast<int>(ev.button);
state = kStateDown;
self->repaint();
return true;
}

return false;
}

bool onMotion(const Widget::MotionEvent& ev)
{
// keep pressed
if (button != -1)
return true;

if (self->contains(ev.pos))
{
// check if entering hover
if (state == kStateNormal)
{
state = kStateHover;
self->repaint();
return true;
}
}
else
{
// check if exiting hover
if (state == kStateHover)
{
state = kStateNormal;
self->repaint();
return true;
}
}

return false;
}

DISTRHO_PREVENT_HEAP_ALLOCATION
DISTRHO_DECLARE_NON_COPYABLE(ButtonImpl)
};

// -----------------------------------------------------------------------

template <class ImageType>
struct ImageBaseKnob<ImageType>::PrivateData {
ImageType image;


+ 232
- 0
dgl/src/EventHandlers.cpp View File

@@ -0,0 +1,232 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2021 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 "../EventHandlers.hpp"
#include "../SubWidget.hpp"

START_NAMESPACE_DGL

// --------------------------------------------------------------------------------------------------------------------

struct ButtonEventHandler::PrivateData {
ButtonEventHandler* const self;
SubWidget* const widget;
ButtonEventHandler::Callback* callback;

int button;
int state;
bool checkable;
bool checked;

Point<double> oldMotionPos;

PrivateData(ButtonEventHandler* const s, SubWidget* const w)
: self(s),
widget(w),
callback(nullptr),
button(-1),
state(kButtonStateDefault),
checkable(false),
checked(false),
oldMotionPos(0, 0) {}

bool mouseEvent(const Widget::MouseEvent& ev)
{
// button was released, handle it now
if (button != -1 && ! ev.press)
{
DISTRHO_SAFE_ASSERT(state & kButtonStateActive);

// release button
const int button2 = button;
button = -1;

const int state2 = state;
state &= ~kButtonStateActive;

// cursor was moved outside the button bounds, ignore click
if (! widget->contains(ev.pos))
{
self->stateChanged(static_cast<State>(state2), static_cast<State>(state));
widget->repaint();
return true;
}

// still on bounds, register click
self->stateChanged(static_cast<State>(state2), static_cast<State>(state));
widget->repaint();

if (checkable)
checked = !checked;

if (callback != nullptr)
callback->buttonClicked(widget, button2);

return true;
}

// button was pressed, wait for release
if (ev.press && widget->contains(ev.pos))
{
const int state2 = state;
button = static_cast<int>(ev.button);
state |= kButtonStateActive;
self->stateChanged(static_cast<State>(state2), static_cast<State>(state));
widget->repaint();
return true;
}

return false;
}

bool motionEvent(const Widget::MotionEvent& ev)
{
// keep pressed
if (button != -1)
{
oldMotionPos = ev.pos;
return true;
}

bool ret = false;

if (widget->contains(ev.pos))
{
// check if entering hover
if ((state & kButtonStateHover) == 0x0)
{
const int state2 = state;
state |= kButtonStateHover;
ret = widget->contains(oldMotionPos);
self->stateChanged(static_cast<State>(state2), static_cast<State>(state));
widget->repaint();
}
}
else
{
// check if exiting hover
if (state & kButtonStateHover)
{
const int state2 = state;
state &= ~kButtonStateHover;
ret = widget->contains(oldMotionPos);
self->stateChanged(static_cast<State>(state2), static_cast<State>(state));
widget->repaint();
}
}

oldMotionPos = ev.pos;
return ret;
}

void setActive(const bool active2, const bool sendCallback) noexcept
{
const bool active = state & kButtonStateActive;
if (active == active2)
return;

state |= kButtonStateActive;
widget->repaint();

if (sendCallback && callback != nullptr)
callback->buttonClicked(widget, -1);
}

void setChecked(const bool checked2, const bool sendCallback) noexcept
{
if (checked == checked2)
return;

checked = checked2;
widget->repaint();

if (sendCallback && callback != nullptr)
callback->buttonClicked(widget, -1);
}

DISTRHO_DECLARE_NON_COPYABLE(PrivateData)
};

// --------------------------------------------------------------------------------------------------------------------

ButtonEventHandler::ButtonEventHandler(SubWidget* const self)
: pData(new PrivateData(this, self)) {}

ButtonEventHandler::~ButtonEventHandler()
{
delete pData;
}

bool ButtonEventHandler::isActive() noexcept
{
return pData->state & kButtonStateActive;
}

void ButtonEventHandler::setActive(const bool active, const bool sendCallback) noexcept
{
pData->setActive(active, sendCallback);
}

bool ButtonEventHandler::isChecked() const noexcept
{
return pData->checked;
}

void ButtonEventHandler::setChecked(const bool checked, const bool sendCallback) noexcept
{
pData->setChecked(checked, sendCallback);
}

bool ButtonEventHandler::isCheckable() const noexcept
{
return pData->checkable;
}

void ButtonEventHandler::setCheckable(const bool checkable) noexcept
{
if (pData->checkable == checkable)
return;

pData->checkable = checkable;
}

void ButtonEventHandler::setCallback(Callback* const callback) noexcept
{
pData->callback = callback;
}

ButtonEventHandler::State ButtonEventHandler::getState() const noexcept
{
return static_cast<State>(pData->state);
}

void ButtonEventHandler::stateChanged(State, State)
{
}

bool ButtonEventHandler::mouseEvent(const Widget::MouseEvent& ev)
{
return pData->mouseEvent(ev);
}

bool ButtonEventHandler::motionEvent(const Widget::MotionEvent& ev)
{
return pData->motionEvent(ev);
}

// --------------------------------------------------------------------------------------------------------------------

END_NAMESPACE_DGL

+ 32
- 19
dgl/src/ImageBaseWidgets.cpp View File

@@ -89,18 +89,25 @@ bool ImageBaseAboutWindow<ImageType>::onMouse(const MouseEvent& ev)
// --------------------------------------------------------------------------------------------------------------------

template <class ImageType>
struct ImageBaseButton<ImageType>::PrivateData {
ButtonImpl<ImageType> impl;
struct ImageBaseButton<ImageType>::PrivateData : public ButtonEventHandler::Callback {
ImageBaseButton<ImageType>::Callback* callback;
ImageType imageNormal;
ImageType imageHover;
ImageType imageDown;

PrivateData(ImageBaseButton<ImageType>* const s, const ImageType& normal, const ImageType& hover, const ImageType& down)
: impl(s),
PrivateData(const ImageType& normal, const ImageType& hover, const ImageType& down)
: callback(nullptr),
imageNormal(normal),
imageHover(hover),
imageDown(down) {}

void buttonClicked(SubWidget* widget, int button) override
{
if (callback != nullptr)
if (ImageBaseButton* const imageButton = dynamic_cast<ImageBaseButton*>(widget))
callback->imageButtonClicked(imageButton, button);
}

DISTRHO_DECLARE_NON_COPYABLE(PrivateData)
};

@@ -109,28 +116,34 @@ struct ImageBaseButton<ImageType>::PrivateData {
template <class ImageType>
ImageBaseButton<ImageType>::ImageBaseButton(Widget* const parentWidget, const ImageType& image)
: SubWidget(parentWidget),
pData(new PrivateData(this, image, image, image))
ButtonEventHandler(this),
pData(new PrivateData(image, image, image))
{
ButtonEventHandler::setCallback(pData);
setSize(image.getSize());
}

template <class ImageType>
ImageBaseButton<ImageType>::ImageBaseButton(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageDown)
: SubWidget(parentWidget),
pData(new PrivateData(this, imageNormal, imageNormal, imageDown))
ButtonEventHandler(this),
pData(new PrivateData(imageNormal, imageNormal, imageDown))
{
DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageDown.getSize());

ButtonEventHandler::setCallback(pData);
setSize(imageNormal.getSize());
}

template <class ImageType>
ImageBaseButton<ImageType>::ImageBaseButton(Widget* const parentWidget, const ImageType& imageNormal, const ImageType& imageHover, const ImageType& imageDown)
: SubWidget(parentWidget),
pData(new PrivateData(this, imageNormal, imageHover, imageDown))
ButtonEventHandler(this),
pData(new PrivateData(imageNormal, imageHover, imageDown))
{
DISTRHO_SAFE_ASSERT(imageNormal.getSize() == imageHover.getSize() && imageHover.getSize() == imageDown.getSize());

ButtonEventHandler::setCallback(pData);
setSize(imageNormal.getSize());
}

@@ -143,7 +156,7 @@ ImageBaseButton<ImageType>::~ImageBaseButton()
template <class ImageType>
void ImageBaseButton<ImageType>::setCallback(Callback* callback) noexcept
{
pData->impl.callback_img = callback;
pData->callback = callback;
}

template <class ImageType>
@@ -151,30 +164,30 @@ void ImageBaseButton<ImageType>::onDisplay()
{
const GraphicsContext& context(getGraphicsContext());

switch (pData->impl.state)
{
case ButtonImpl<ImageType>::kStateDown:
const State state = ButtonEventHandler::getState();
if (state & kButtonStateActive)
pData->imageDown.draw(context);
break;
case ButtonImpl<ImageType>::kStateHover:
else if (state & kButtonStateHover)
pData->imageHover.draw(context);
break;
default:
else
pData->imageNormal.draw(context);
break;
}
}

template <class ImageType>
bool ImageBaseButton<ImageType>::onMouse(const MouseEvent& ev)
{
return pData->impl.onMouse(ev);
if (SubWidget::onMouse(ev))
return true;
return ButtonEventHandler::mouseEvent(ev);
}

template <class ImageType>
bool ImageBaseButton<ImageType>::onMotion(const MotionEvent& ev)
{
return pData->impl.onMotion(ev);
if (SubWidget::onMotion(ev))
return true;
return ButtonEventHandler::motionEvent(ev);
}

// --------------------------------------------------------------------------------------------------------------------


Loading…
Cancel
Save