| @@ -0,0 +1,62 @@ | |||
| /* | |||
| * DISTRHO Plugin Toolkit (DPT) | |||
| * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LGPL.txt file | |||
| */ | |||
| #ifndef __DGL_IMAGE_BUTTON_HPP__ | |||
| #define __DGL_IMAGE_BUTTON_HPP__ | |||
| #include "Image.hpp" | |||
| #include "Widget.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| // ------------------------------------------------- | |||
| class ImageButton : public Widget | |||
| { | |||
| public: | |||
| class Callback | |||
| { | |||
| public: | |||
| virtual ~Callback() {} | |||
| virtual void imageButtonClicked(ImageButton* imageButton, int button) = 0; | |||
| }; | |||
| ImageButton(Window* parent, const Image& image); | |||
| ImageButton(Window* parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown); | |||
| ImageButton(const ImageButton& imageButton); | |||
| void setCallback(Callback* callback); | |||
| protected: | |||
| void onDisplay(); | |||
| bool onMouse(int button, bool press, int x, int y); | |||
| bool onMotion(int x, int y); | |||
| private: | |||
| Image fImageNormal; | |||
| Image fImageHover; | |||
| Image fImageDown; | |||
| Image* fCurImage; | |||
| int fCurButton; | |||
| Callback* fCallback; | |||
| }; | |||
| // ------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| #endif // __DGL_IMAGE_BUTTON_HPP__ | |||
| @@ -17,7 +17,7 @@ | |||
| #ifndef __DGL_WIDGET_HPP__ | |||
| #define __DGL_WIDGET_HPP__ | |||
| #include "Base.hpp" | |||
| #include "Geometry.hpp" | |||
| START_NAMESPACE_DISTRHO | |||
| @@ -44,19 +44,47 @@ public: | |||
| setVisible(false); | |||
| } | |||
| int getX() const; | |||
| int getY() const; | |||
| const Point<int>& getPos() const; | |||
| void setX(int x); | |||
| void setY(int y); | |||
| void setPos(int x, int y); | |||
| void setPos(const Point<int>& pos); | |||
| void move(int x, int y); | |||
| void move(const Point<int>& pos); | |||
| int getWidth() const; | |||
| int getHeight() const; | |||
| const Size<int>& getSize() const; | |||
| void setWidth(int width); | |||
| void setHeight(int height); | |||
| void setSize(int width, int height); | |||
| void setSize(const Size<int>& size); | |||
| const Rectangle<int>& getArea() const; | |||
| Window* getParent() const; | |||
| void repaint(); | |||
| protected: | |||
| virtual void onDisplay(); | |||
| virtual void onKeyboard(bool press, uint32_t key); | |||
| virtual void onMouse(int button, bool press, int x, int y); | |||
| virtual void onMotion(int x, int y); | |||
| virtual void onScroll(float dx, float dy); | |||
| virtual void onSpecial(bool press, Key key); | |||
| virtual bool onKeyboard(bool press, uint32_t key); | |||
| virtual bool onMouse(int button, bool press, int x, int y); | |||
| virtual bool onMotion(int x, int y); | |||
| virtual bool onScroll(float dx, float dy); | |||
| virtual bool onSpecial(bool press, Key key); | |||
| virtual void onReshape(int width, int height); | |||
| virtual void onClose(); | |||
| private: | |||
| Window* fParent; | |||
| bool fVisible; | |||
| bool fVisible; | |||
| Rectangle<int> fArea; | |||
| friend class Window; | |||
| }; | |||
| @@ -97,7 +97,7 @@ void Image::draw(const Point<int>& pos) | |||
| if (! isValid()) | |||
| return; | |||
| glRasterPos2i(pos.getX(), fSize.getHeight()-pos.getY()); | |||
| glRasterPos2i(pos.getX(), fSize.getHeight()+pos.getY()); | |||
| glDrawPixels(fSize.getWidth(), fSize.getHeight(), fFormat, fType, fRawData); | |||
| } | |||
| @@ -0,0 +1,148 @@ | |||
| /* | |||
| * DISTRHO Plugin Toolkit (DPT) | |||
| * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU Lesser General Public License for more details. | |||
| * | |||
| * For a full copy of the license see the LGPL.txt file | |||
| */ | |||
| #include "../ImageButton.hpp" | |||
| #include <cassert> | |||
| #include <cstdio> | |||
| START_NAMESPACE_DISTRHO | |||
| // ------------------------------------------------- | |||
| ImageButton::ImageButton(Window* parent, const Image& image) | |||
| : Widget(parent), | |||
| fImageNormal(image), | |||
| fImageHover(image), | |||
| fImageDown(image), | |||
| fCurImage(&fImageNormal), | |||
| fCurButton(-1), | |||
| fCallback(nullptr) | |||
| { | |||
| } | |||
| ImageButton::ImageButton(Window* parent, const Image& imageNormal, const Image& imageHover, const Image& imageDown) | |||
| : Widget(parent), | |||
| fImageNormal(imageNormal), | |||
| fImageHover(imageHover), | |||
| fImageDown(imageDown), | |||
| fCurImage(&fImageNormal), | |||
| fCurButton(-1), | |||
| fCallback(nullptr) | |||
| { | |||
| assert(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); | |||
| setSize(fCurImage->getSize()); | |||
| } | |||
| ImageButton::ImageButton(const ImageButton& imageButton) | |||
| : Widget(imageButton.getParent()), | |||
| fImageNormal(imageButton.fImageNormal), | |||
| fImageHover(imageButton.fImageHover), | |||
| fImageDown(imageButton.fImageDown), | |||
| fCurImage(&fImageNormal), | |||
| fCurButton(-1), | |||
| fCallback(nullptr) | |||
| { | |||
| assert(fImageNormal.getSize() == fImageHover.getSize() && fImageHover.getSize() == fImageDown.getSize()); | |||
| setSize(fCurImage->getSize()); | |||
| } | |||
| void ImageButton::setCallback(Callback* callback) | |||
| { | |||
| fCallback = callback; | |||
| } | |||
| void ImageButton::onDisplay() | |||
| { | |||
| fCurImage->draw(getPos()); | |||
| } | |||
| bool ImageButton::onMouse(int button, bool press, int x, int y) | |||
| { | |||
| if (fCurButton != -1 && ! press) | |||
| { | |||
| if (getArea().contains(x, y)) | |||
| { | |||
| if (fCurImage != &fImageHover) | |||
| { | |||
| fCurImage = &fImageHover; | |||
| repaint(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| if (fCurImage != &fImageNormal) | |||
| { | |||
| fCurImage = &fImageNormal; | |||
| repaint(); | |||
| } | |||
| } | |||
| if (fCallback != nullptr) | |||
| fCallback->imageButtonClicked(this, fCurButton); | |||
| fCurButton = -1; | |||
| return true; | |||
| } | |||
| if (press && getArea().contains(x, y)) | |||
| { | |||
| if (fCurImage != &fImageDown) | |||
| { | |||
| fCurImage = &fImageDown; | |||
| repaint(); | |||
| } | |||
| fCurButton = button; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| bool ImageButton::onMotion(int x, int y) | |||
| { | |||
| if (fCurButton != -1) | |||
| return true; | |||
| if (getArea().contains(x, y)) | |||
| { | |||
| if (fCurImage != &fImageHover) | |||
| { | |||
| fCurImage = &fImageHover; | |||
| repaint(); | |||
| } | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| if (fCurImage != &fImageNormal) | |||
| { | |||
| fCurImage = &fImageNormal; | |||
| repaint(); | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| // ------------------------------------------------- | |||
| END_NAMESPACE_DISTRHO | |||
| @@ -50,27 +50,148 @@ void Widget::setVisible(bool yesNo) | |||
| fParent->repaint(); | |||
| } | |||
| int Widget::getX() const | |||
| { | |||
| return fArea.getX(); | |||
| } | |||
| int Widget::getY() const | |||
| { | |||
| return fArea.getY(); | |||
| } | |||
| const Point<int>& Widget::getPos() const | |||
| { | |||
| return fArea.getPos(); | |||
| } | |||
| void Widget::setX(int x) | |||
| { | |||
| if (fArea.getX() == x) | |||
| return; | |||
| fArea.setX(x); | |||
| repaint(); | |||
| } | |||
| void Widget::setY(int y) | |||
| { | |||
| if (fArea.getY() == y) | |||
| return; | |||
| fArea.setY(y); | |||
| repaint(); | |||
| } | |||
| void Widget::setPos(int x, int y) | |||
| { | |||
| setPos(Point<int>(x, y)); | |||
| } | |||
| void Widget::setPos(const Point<int>& pos) | |||
| { | |||
| if (fArea.getPos() == pos) | |||
| return; | |||
| fArea.setPos(pos); | |||
| repaint(); | |||
| } | |||
| void Widget::move(int x, int y) | |||
| { | |||
| fArea.move(x, y); | |||
| repaint(); | |||
| } | |||
| void Widget::move(const Point<int>& pos) | |||
| { | |||
| fArea.move(pos); | |||
| repaint(); | |||
| } | |||
| int Widget::getWidth() const | |||
| { | |||
| return fArea.getWidth(); | |||
| } | |||
| int Widget::getHeight() const | |||
| { | |||
| return fArea.getHeight(); | |||
| } | |||
| const Size<int>& Widget::getSize() const | |||
| { | |||
| return fArea.getSize(); | |||
| } | |||
| void Widget::setWidth(int width) | |||
| { | |||
| if (fArea.getWidth() == width) | |||
| return; | |||
| fArea.setWidth(width); | |||
| fParent->repaint(); | |||
| } | |||
| void Widget::setHeight(int height) | |||
| { | |||
| if (fArea.getHeight() == height) | |||
| return; | |||
| fArea.setHeight(height); | |||
| fParent->repaint(); | |||
| } | |||
| void Widget::setSize(int width, int height) | |||
| { | |||
| setSize(Size<int>(width, height)); | |||
| } | |||
| void Widget::setSize(const Size<int>& size) | |||
| { | |||
| if (fArea.getSize() == size) | |||
| return; | |||
| fArea.setSize(size); | |||
| fParent->repaint(); | |||
| } | |||
| const Rectangle<int>& Widget::getArea() const | |||
| { | |||
| return fArea; | |||
| } | |||
| Window* Widget::getParent() const | |||
| { | |||
| return fParent; | |||
| } | |||
| void Widget::repaint() | |||
| { | |||
| fParent->repaint(); | |||
| } | |||
| void Widget::onDisplay() | |||
| { | |||
| } | |||
| void Widget::onKeyboard(bool, uint32_t) | |||
| bool Widget::onKeyboard(bool, uint32_t) | |||
| { | |||
| } | |||
| void Widget::onMouse(int, bool, int, int) | |||
| bool Widget::onMouse(int, bool, int, int) | |||
| { | |||
| } | |||
| void Widget::onMotion(int, int) | |||
| bool Widget::onMotion(int, int) | |||
| { | |||
| } | |||
| void Widget::onScroll(float, float) | |||
| bool Widget::onScroll(float, float) | |||
| { | |||
| } | |||
| void Widget::onSpecial(bool, Key) | |||
| bool Widget::onSpecial(bool, Key) | |||
| { | |||
| } | |||
| @@ -47,7 +47,10 @@ static Bool isUnmapNotify(Display*, XEvent* ev, XPointer win) | |||
| #endif | |||
| #define FOR_EACH_WIDGET(it) \ | |||
| for (auto it = fWidgets.begin(); it != fWidgets.end(); it++) | |||
| for (auto it = fWidgets.begin(); it != fWidgets.end(); ++it) | |||
| #define FOR_EACH_WIDGET_INV(rit) \ | |||
| for (auto rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit) | |||
| // ------------------------------------------------- | |||
| // Window Private | |||
| @@ -305,11 +308,14 @@ protected: | |||
| if (fChildFocus != nullptr) | |||
| return fChildFocus->focus(); | |||
| FOR_EACH_WIDGET(it) | |||
| FOR_EACH_WIDGET_INV(rit) | |||
| { | |||
| Widget* widget = *it; | |||
| Widget* widget = *rit; | |||
| if (widget->isVisible()) | |||
| widget->onKeyboard(press, key); | |||
| { | |||
| if (widget->onKeyboard(press, key)) | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| @@ -318,11 +324,14 @@ protected: | |||
| if (fChildFocus != nullptr) | |||
| return fChildFocus->focus(); | |||
| FOR_EACH_WIDGET(it) | |||
| FOR_EACH_WIDGET_INV(rit) | |||
| { | |||
| Widget* widget = *it; | |||
| Widget* widget = *rit; | |||
| if (widget->isVisible()) | |||
| widget->onMouse(button, press, x, y); | |||
| { | |||
| if (widget->onMouse(button, press, x, y)) | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| @@ -331,11 +340,14 @@ protected: | |||
| if (fChildFocus != nullptr) | |||
| return; | |||
| FOR_EACH_WIDGET(it) | |||
| FOR_EACH_WIDGET_INV(rit) | |||
| { | |||
| Widget* widget = *it; | |||
| Widget* widget = *rit; | |||
| if (widget->isVisible()) | |||
| widget->onMotion(x, y); | |||
| { | |||
| if (widget->onMotion(x, y)) | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| @@ -344,11 +356,14 @@ protected: | |||
| if (fChildFocus != nullptr) | |||
| return; | |||
| FOR_EACH_WIDGET(it) | |||
| FOR_EACH_WIDGET_INV(rit) | |||
| { | |||
| Widget* widget = *it; | |||
| Widget* widget = *rit; | |||
| if (widget->isVisible()) | |||
| widget->onScroll(dx, dy); | |||
| { | |||
| if (widget->onScroll(dx, dy)) | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| @@ -357,11 +372,14 @@ protected: | |||
| if (fChildFocus != nullptr) | |||
| return; | |||
| FOR_EACH_WIDGET(it) | |||
| FOR_EACH_WIDGET_INV(rit) | |||
| { | |||
| Widget* widget = *it; | |||
| Widget* widget = *rit; | |||
| if (widget->isVisible()) | |||
| widget->onSpecial(press, key); | |||
| { | |||
| if (widget->onSpecial(press, key)) | |||
| break; | |||
| } | |||
| } | |||
| } | |||