| @@ -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__ | #ifndef __DGL_WIDGET_HPP__ | ||||
| #define __DGL_WIDGET_HPP__ | #define __DGL_WIDGET_HPP__ | ||||
| #include "Base.hpp" | |||||
| #include "Geometry.hpp" | |||||
| START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
| @@ -44,19 +44,47 @@ public: | |||||
| setVisible(false); | 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: | protected: | ||||
| virtual void onDisplay(); | 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 onReshape(int width, int height); | ||||
| virtual void onClose(); | virtual void onClose(); | ||||
| private: | private: | ||||
| Window* fParent; | Window* fParent; | ||||
| bool fVisible; | |||||
| bool fVisible; | |||||
| Rectangle<int> fArea; | |||||
| friend class Window; | friend class Window; | ||||
| }; | }; | ||||
| @@ -97,7 +97,7 @@ void Image::draw(const Point<int>& pos) | |||||
| if (! isValid()) | if (! isValid()) | ||||
| return; | return; | ||||
| glRasterPos2i(pos.getX(), fSize.getHeight()-pos.getY()); | |||||
| glRasterPos2i(pos.getX(), fSize.getHeight()+pos.getY()); | |||||
| glDrawPixels(fSize.getWidth(), fSize.getHeight(), fFormat, fType, fRawData); | 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(); | 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::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 | #endif | ||||
| #define FOR_EACH_WIDGET(it) \ | #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 | // Window Private | ||||
| @@ -305,11 +308,14 @@ protected: | |||||
| if (fChildFocus != nullptr) | if (fChildFocus != nullptr) | ||||
| return fChildFocus->focus(); | return fChildFocus->focus(); | ||||
| FOR_EACH_WIDGET(it) | |||||
| FOR_EACH_WIDGET_INV(rit) | |||||
| { | { | ||||
| Widget* widget = *it; | |||||
| Widget* widget = *rit; | |||||
| if (widget->isVisible()) | if (widget->isVisible()) | ||||
| widget->onKeyboard(press, key); | |||||
| { | |||||
| if (widget->onKeyboard(press, key)) | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -318,11 +324,14 @@ protected: | |||||
| if (fChildFocus != nullptr) | if (fChildFocus != nullptr) | ||||
| return fChildFocus->focus(); | return fChildFocus->focus(); | ||||
| FOR_EACH_WIDGET(it) | |||||
| FOR_EACH_WIDGET_INV(rit) | |||||
| { | { | ||||
| Widget* widget = *it; | |||||
| Widget* widget = *rit; | |||||
| if (widget->isVisible()) | 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) | if (fChildFocus != nullptr) | ||||
| return; | return; | ||||
| FOR_EACH_WIDGET(it) | |||||
| FOR_EACH_WIDGET_INV(rit) | |||||
| { | { | ||||
| Widget* widget = *it; | |||||
| Widget* widget = *rit; | |||||
| if (widget->isVisible()) | if (widget->isVisible()) | ||||
| widget->onMotion(x, y); | |||||
| { | |||||
| if (widget->onMotion(x, y)) | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -344,11 +356,14 @@ protected: | |||||
| if (fChildFocus != nullptr) | if (fChildFocus != nullptr) | ||||
| return; | return; | ||||
| FOR_EACH_WIDGET(it) | |||||
| FOR_EACH_WIDGET_INV(rit) | |||||
| { | { | ||||
| Widget* widget = *it; | |||||
| Widget* widget = *rit; | |||||
| if (widget->isVisible()) | if (widget->isVisible()) | ||||
| widget->onScroll(dx, dy); | |||||
| { | |||||
| if (widget->onScroll(dx, dy)) | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -357,11 +372,14 @@ protected: | |||||
| if (fChildFocus != nullptr) | if (fChildFocus != nullptr) | ||||
| return; | return; | ||||
| FOR_EACH_WIDGET(it) | |||||
| FOR_EACH_WIDGET_INV(rit) | |||||
| { | { | ||||
| Widget* widget = *it; | |||||
| Widget* widget = *rit; | |||||
| if (widget->isVisible()) | if (widget->isVisible()) | ||||
| widget->onSpecial(press, key); | |||||
| { | |||||
| if (widget->onSpecial(press, key)) | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||