| @@ -23,30 +23,108 @@ START_NAMESPACE_DGL | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| /** | |||||
| Base DGL Image class. | |||||
| This is an Image class that handles raw image data in pixels. | |||||
| You can init the image data on the contructor or later on by calling loadFromMemory(). | |||||
| To generate raw data useful for this class see the utils/png2rgba.py script. | |||||
| Be careful when using a PNG without alpha channel, for those the format is 'GL_BGR' | |||||
| instead of the default 'GL_BGRA'. | |||||
| Images are drawn on screen via 2D textures. | |||||
| */ | |||||
| class Image | class Image | ||||
| { | { | ||||
| public: | public: | ||||
| /** | |||||
| Constructor for a null Image. | |||||
| */ | |||||
| Image() noexcept; | Image() noexcept; | ||||
| /** | |||||
| Constructor using raw image data. | |||||
| @note @a rawData must remain valid for the lifetime of this Image. | |||||
| */ | |||||
| Image(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | Image(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | ||||
| /** | |||||
| Constructor using raw image data. | |||||
| @note @a rawData must remain valid for the lifetime of this Image. | |||||
| */ | |||||
| Image(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | Image(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | ||||
| /** | |||||
| Constructor using another image data. | |||||
| */ | |||||
| Image(const Image& image) noexcept; | Image(const Image& image) noexcept; | ||||
| /** | |||||
| Destructor. | |||||
| */ | |||||
| ~Image(); | ~Image(); | ||||
| /** | |||||
| Load image data from memory. | |||||
| @note @a rawData must remain valid for the lifetime of this Image. | |||||
| */ | |||||
| void loadFromMemory(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | void loadFromMemory(const char* rawData, int width, int height, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | ||||
| /** | |||||
| Load image data from memory. | |||||
| @note @a rawData must remain valid for the lifetime of this Image. | |||||
| */ | |||||
| void loadFromMemory(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | void loadFromMemory(const char* rawData, const Size<int>& size, GLenum format = GL_BGRA, GLenum type = GL_UNSIGNED_BYTE) noexcept; | ||||
| /** | |||||
| Check if this image is valid. | |||||
| */ | |||||
| bool isValid() const noexcept; | bool isValid() const noexcept; | ||||
| /** | |||||
| Get width. | |||||
| */ | |||||
| int getWidth() const noexcept; | int getWidth() const noexcept; | ||||
| /** | |||||
| Get height. | |||||
| */ | |||||
| int getHeight() const noexcept; | int getHeight() const noexcept; | ||||
| /** | |||||
| Get size. | |||||
| */ | |||||
| const Size<int>& getSize() const noexcept; | const Size<int>& getSize() const noexcept; | ||||
| /** | |||||
| Get the raw image data. | |||||
| */ | |||||
| const char* getRawData() const noexcept; | const char* getRawData() const noexcept; | ||||
| /** | |||||
| Get the image format. | |||||
| */ | |||||
| GLenum getFormat() const noexcept; | GLenum getFormat() const noexcept; | ||||
| /** | |||||
| Get the image type. | |||||
| */ | |||||
| GLenum getType() const noexcept; | GLenum getType() const noexcept; | ||||
| /** | |||||
| Draw this image at (0, 0) point. | |||||
| */ | |||||
| void draw(); | void draw(); | ||||
| /** | |||||
| Draw this image at (x, y) point. | |||||
| */ | |||||
| void drawAt(int x, int y); | void drawAt(int x, int y); | ||||
| /** | |||||
| Draw this image at position @a pos. | |||||
| */ | |||||
| void drawAt(const Point<int>& pos); | void drawAt(const Point<int>& pos); | ||||
| Image& operator=(const Image& image) noexcept; | Image& operator=(const Image& image) noexcept; | ||||
| @@ -36,8 +36,8 @@ public: | |||||
| protected: | protected: | ||||
| void onDisplay() override; | void onDisplay() override; | ||||
| bool onMouse(int button, bool press, int x, int y) override; | |||||
| bool onKeyboard(bool press, uint key) override; | |||||
| bool onKeyboard(const KeyboardEvent&) override; | |||||
| bool onMouse(const MouseEvent&) override; | |||||
| private: | private: | ||||
| Image fImgBackground; | Image fImgBackground; | ||||
| @@ -44,8 +44,8 @@ public: | |||||
| protected: | protected: | ||||
| void onDisplay() override; | void onDisplay() override; | ||||
| bool onMouse(int button, bool press, int x, int y) override; | |||||
| bool onMotion(int x, int y) override; | |||||
| bool onMouse(const MouseEvent&) override; | |||||
| bool onMotion(const MotionEvent&) override; | |||||
| private: | private: | ||||
| Image fImageNormal; | Image fImageNormal; | ||||
| @@ -44,6 +44,7 @@ public: | |||||
| ImageKnob(Window& parent, const Image& image, Orientation orientation = Vertical, int id = 0) noexcept; | ImageKnob(Window& parent, const Image& image, Orientation orientation = Vertical, int id = 0) noexcept; | ||||
| ImageKnob(Widget* widget, const Image& image, Orientation orientation = Vertical, int id = 0) noexcept; | ImageKnob(Widget* widget, const Image& image, Orientation orientation = Vertical, int id = 0) noexcept; | ||||
| ImageKnob(const ImageKnob& imageKnob); | ImageKnob(const ImageKnob& imageKnob); | ||||
| ~ImageKnob() override; | |||||
| int getId() const noexcept; | int getId() const noexcept; | ||||
| void setId(int id) noexcept; | void setId(int id) noexcept; | ||||
| @@ -60,10 +61,9 @@ public: | |||||
| protected: | protected: | ||||
| void onDisplay() override; | void onDisplay() override; | ||||
| bool onMouse(int button, bool press, int x, int y) override; | |||||
| bool onMotion(int x, int y) override; | |||||
| void onReshape(int width, int height) override; | |||||
| void onClose() override; | |||||
| bool onMouse(const MouseEvent&) override; | |||||
| bool onMotion(const MotionEvent&) override; | |||||
| void onResize(const ResizeEvent&) override; | |||||
| private: | private: | ||||
| Image fImage; | Image fImage; | ||||
| @@ -59,8 +59,8 @@ public: | |||||
| protected: | protected: | ||||
| void onDisplay() override; | void onDisplay() override; | ||||
| bool onMouse(int button, bool press, int x, int y) override; | |||||
| bool onMotion(int x, int y) override; | |||||
| bool onMouse(const MouseEvent&) override; | |||||
| bool onMotion(const MotionEvent&) override; | |||||
| private: | private: | ||||
| Image fImage; | Image fImage; | ||||
| @@ -22,45 +22,222 @@ | |||||
| START_NAMESPACE_DGL | START_NAMESPACE_DGL | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // Forward class names | |||||
| class App; | class App; | ||||
| class Window; | class Window; | ||||
| // ----------------------------------------------------------------------- | |||||
| /** | |||||
| Base DGL Widget class. | |||||
| This is the base Widget class, from which all widgets are built. | |||||
| All widgets have a parent Window where they'll be drawn. | |||||
| This parent is never changed during the widget lifetime. | |||||
| Widgets receive events in relative coordinates. | |||||
| (0, 0) means its top-left position. | |||||
| Windows paint widgets in the order they are constructed. | |||||
| Early widgets are drawn first, at the bottom, then newer ones on top. | |||||
| Events are sent in the inverse order so that the top-most widget gets | |||||
| a chance to catch the event and stop its propagation. | |||||
| All widget event callbacks do nothing by default. | |||||
| */ | |||||
| class Widget | class Widget | ||||
| { | { | ||||
| public: | public: | ||||
| /** | |||||
| Base event data. | |||||
| @param mod The currently active modifiers. | |||||
| @param time The timestamp (if any) of the currently-processing event. | |||||
| */ | |||||
| struct BaseEvent { | |||||
| Modifier mod; | |||||
| uint32_t time; | |||||
| }; | |||||
| /** | |||||
| Keyboard event. | |||||
| @param press True if the key was pressed, false if released. | |||||
| @param key Unicode point of the key pressed. | |||||
| @see onKeyboard | |||||
| */ | |||||
| struct KeyboardEvent : BaseEvent { | |||||
| bool press; | |||||
| uint key; | |||||
| }; | |||||
| /** | |||||
| Special keyboard event. | |||||
| @param press True if the key was pressed, false if released. | |||||
| @param key The key pressed. | |||||
| @see onSpecial | |||||
| */ | |||||
| struct SpecialEvent : BaseEvent { | |||||
| bool press; | |||||
| Key key; | |||||
| }; | |||||
| /** | |||||
| Mouse event. | |||||
| @param button The button number (1 = left, 2 = middle, 3 = right). | |||||
| @param press True if the key was pressed, false if released. | |||||
| @param pos The widget-relative coordinates of the pointer. | |||||
| @see onMouse | |||||
| */ | |||||
| struct MouseEvent : BaseEvent { | |||||
| int button; | |||||
| bool press; | |||||
| Point<int> pos; | |||||
| }; | |||||
| /** | |||||
| Mouse motion event. | |||||
| @param x The widget-relative coordinates of the pointer. | |||||
| @see onMotion | |||||
| */ | |||||
| struct MotionEvent : BaseEvent { | |||||
| Point<int> pos; | |||||
| }; | |||||
| /** | |||||
| Mouse scroll event. | |||||
| @param pos The scroll distance. | |||||
| @param _ TODO | |||||
| @see onScroll | |||||
| */ | |||||
| struct ScrollEvent : BaseEvent { | |||||
| Point<int> pos; | |||||
| Point<float> _; | |||||
| }; | |||||
| /** | |||||
| Resize event. | |||||
| @param size The new widget size | |||||
| @param oldSize The previous size, may be null | |||||
| @see onResize | |||||
| */ | |||||
| struct ResizeEvent { | |||||
| Size<int> size; | |||||
| Size<int> oldSize; | |||||
| }; | |||||
| /** | |||||
| Constructor. | |||||
| */ | |||||
| explicit Widget(Window& parent); | explicit Widget(Window& parent); | ||||
| /** | |||||
| Destructor. | |||||
| */ | |||||
| virtual ~Widget(); | virtual ~Widget(); | ||||
| /** | |||||
| Check if this widget is visible within its parent window. | |||||
| Invisible widgets do not receive events except resize. | |||||
| */ | |||||
| bool isVisible() const noexcept; | bool isVisible() const noexcept; | ||||
| /** | |||||
| Set widget visible (or not) according to @a yesNo. | |||||
| */ | |||||
| void setVisible(bool yesNo); | void setVisible(bool yesNo); | ||||
| /** | |||||
| Show widget. | |||||
| This is the same as calling setVisible(true). | |||||
| */ | |||||
| void show(); | void show(); | ||||
| void hide(); | |||||
| int getX() const noexcept; | |||||
| int getY() const noexcept; | |||||
| const Point<int>& getPos() const noexcept; | |||||
| void setX(int x) noexcept; | |||||
| void setY(int y) noexcept; | |||||
| void setPos(int x, int y) noexcept; | |||||
| void setPos(const Point<int>& pos) noexcept; | |||||
| /** | |||||
| Hide widget. | |||||
| This is the same as calling setVisible(false). | |||||
| */ | |||||
| void hide(); | |||||
| /** | |||||
| Get width. | |||||
| */ | |||||
| int getWidth() const noexcept; | int getWidth() const noexcept; | ||||
| /** | |||||
| Get height. | |||||
| */ | |||||
| int getHeight() const noexcept; | int getHeight() const noexcept; | ||||
| /** | |||||
| Get size. | |||||
| */ | |||||
| const Size<int>& getSize() const noexcept; | const Size<int>& getSize() const noexcept; | ||||
| // virtual needed by cairo | |||||
| /** | |||||
| Set width. | |||||
| */ | |||||
| virtual void setWidth(int width) noexcept; | virtual void setWidth(int width) noexcept; | ||||
| /** | |||||
| Set height. | |||||
| */ | |||||
| virtual void setHeight(int height) noexcept; | virtual void setHeight(int height) noexcept; | ||||
| /** | |||||
| Set size using @a width and @a height values. | |||||
| */ | |||||
| virtual void setSize(int width, int height) noexcept; | virtual void setSize(int width, int height) noexcept; | ||||
| /** | |||||
| Set size. | |||||
| */ | |||||
| virtual void setSize(const Size<int>& size) noexcept; | virtual void setSize(const Size<int>& size) noexcept; | ||||
| uint getEventTimestamp() const noexcept; | |||||
| int getModifiers() const noexcept; | |||||
| /** | |||||
| Get absolute X. | |||||
| */ | |||||
| int getAbsoluteX() const noexcept; | |||||
| /** | |||||
| Get absolute Y. | |||||
| */ | |||||
| int getAbsoluteY() const noexcept; | |||||
| /** | |||||
| Get absolute position. | |||||
| */ | |||||
| const Point<int>& getAbsolutePos() const noexcept; | |||||
| /** | |||||
| Set absolute X. | |||||
| */ | |||||
| void setAbsoluteX(int x) noexcept; | |||||
| /** | |||||
| Set absolute Y. | |||||
| */ | |||||
| void setAbsoluteY(int y) noexcept; | |||||
| /** | |||||
| Set absolute position using @a x and @a y values. | |||||
| */ | |||||
| void setAbsolutePos(int x, int y) noexcept; | |||||
| /** | |||||
| Set absolute position. | |||||
| */ | |||||
| void setAbsolutePos(const Point<int>& pos) noexcept; | |||||
| /** | |||||
| Get this widget's window application. | |||||
| Same as calling getParentWindow().getApp(). | |||||
| */ | |||||
| App& getParentApp() const noexcept; | |||||
| App& getParentApp() const noexcept; | |||||
| /** | |||||
| Get parent window, as passed in the constructor. | |||||
| */ | |||||
| Window& getParentWindow() const noexcept; | Window& getParentWindow() const noexcept; | ||||
| /** | /** | ||||
| @@ -73,16 +250,51 @@ public: | |||||
| */ | */ | ||||
| bool contains(const Point<int>& pos) const noexcept; | bool contains(const Point<int>& pos) const noexcept; | ||||
| /** | |||||
| Tell this widget's window to repaint itself. | |||||
| */ | |||||
| void repaint() noexcept; | void repaint() noexcept; | ||||
| protected: | protected: | ||||
| /** | |||||
| A function called to draw the view contents with OpenGL. | |||||
| */ | |||||
| virtual void onDisplay() = 0; | virtual void onDisplay() = 0; | ||||
| virtual bool onKeyboard(bool press, uint key); | |||||
| virtual bool onMouse(int button, bool press, int x, int y); | |||||
| virtual bool onMotion(int x, int y); | |||||
| virtual bool onScroll(int x, int y, float dx, float dy); | |||||
| virtual bool onSpecial(bool press, Key key); | |||||
| virtual void onReshape(int width, int height); | |||||
| /** | |||||
| A function called when a key is pressed or released. | |||||
| @return True to stop event propagation, false otherwise. | |||||
| */ | |||||
| virtual bool onKeyboard(const KeyboardEvent&); | |||||
| /** | |||||
| A function called when a special key is pressed or released. | |||||
| @return True to stop event propagation, false otherwise. | |||||
| */ | |||||
| virtual bool onSpecial(const SpecialEvent&); | |||||
| /** | |||||
| A function called when a mouse button is pressed or released. | |||||
| @return True to stop event propagation, false otherwise. | |||||
| */ | |||||
| virtual bool onMouse(const MouseEvent&); | |||||
| /** | |||||
| A function called when the pointer moves. | |||||
| @return True to stop event propagation, false otherwise. | |||||
| */ | |||||
| virtual bool onMotion(const MotionEvent&); | |||||
| /** | |||||
| A function called on scrolling (e.g. mouse wheel or track pad). | |||||
| @return True to stop event propagation, false otherwise. | |||||
| */ | |||||
| virtual bool onScroll(const ScrollEvent&); | |||||
| /** | |||||
| A function called when the widget is resized. | |||||
| */ | |||||
| virtual void onResize(const ResizeEvent&); | |||||
| private: | private: | ||||
| Window& fParent; | Window& fParent; | ||||
| @@ -59,8 +59,6 @@ public: | |||||
| void setTransientWinId(intptr_t winId); | void setTransientWinId(intptr_t winId); | ||||
| App& getApp() const noexcept; | App& getApp() const noexcept; | ||||
| uint getEventTimestamp() const noexcept; | |||||
| int getModifiers() const noexcept; | |||||
| intptr_t getWindowId() const noexcept; | intptr_t getWindowId() const noexcept; | ||||
| void addIdleCallback(IdleCallback* const callback); | void addIdleCallback(IdleCallback* const callback); | ||||
| @@ -69,8 +67,8 @@ public: | |||||
| protected: | protected: | ||||
| virtual void onDisplayBefore(); | virtual void onDisplayBefore(); | ||||
| virtual void onDisplayAfter(); | virtual void onDisplayAfter(); | ||||
| virtual void onClose(); | |||||
| virtual void onReshape(int width, int height); | virtual void onReshape(int width, int height); | ||||
| virtual void onClose(); | |||||
| private: | private: | ||||
| struct PrivateData; | struct PrivateData; | ||||
| @@ -54,9 +54,9 @@ void ImageAboutWindow::onDisplay() | |||||
| fImgBackground.draw(); | fImgBackground.draw(); | ||||
| } | } | ||||
| bool ImageAboutWindow::onMouse(int, bool press, int, int) | |||||
| bool ImageAboutWindow::onKeyboard(const KeyboardEvent& ev) | |||||
| { | { | ||||
| if (press) | |||||
| if (ev.press && ev.key == CHAR_ESCAPE) | |||||
| { | { | ||||
| Window::close(); | Window::close(); | ||||
| return true; | return true; | ||||
| @@ -65,9 +65,9 @@ bool ImageAboutWindow::onMouse(int, bool press, int, int) | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool ImageAboutWindow::onKeyboard(bool press, uint key) | |||||
| bool ImageAboutWindow::onMouse(const MouseEvent& ev) | |||||
| { | { | ||||
| if (press && key == CHAR_ESCAPE) | |||||
| if (ev.press) | |||||
| { | { | ||||
| Window::close(); | Window::close(); | ||||
| return true; | return true; | ||||
| @@ -91,12 +91,12 @@ void ImageButton::setCallback(Callback* callback) noexcept | |||||
| void ImageButton::onDisplay() | void ImageButton::onDisplay() | ||||
| { | { | ||||
| fCurImage->drawAt(getPos()); | |||||
| fCurImage->draw(); | |||||
| } | } | ||||
| bool ImageButton::onMouse(int button, bool press, int x, int y) | |||||
| bool ImageButton::onMouse(const MouseEvent& ev) | |||||
| { | { | ||||
| if (fCurButton != -1 && ! press) | |||||
| if (fCurButton != -1 && ! ev.press) | |||||
| { | { | ||||
| if (fCurImage != &fImageNormal) | if (fCurImage != &fImageNormal) | ||||
| { | { | ||||
| @@ -104,7 +104,7 @@ bool ImageButton::onMouse(int button, bool press, int x, int y) | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| if (! contains(x, y)) | |||||
| if (! contains(ev.pos)) | |||||
| { | { | ||||
| fCurButton = -1; | fCurButton = -1; | ||||
| return false; | return false; | ||||
| @@ -113,18 +113,20 @@ bool ImageButton::onMouse(int button, bool press, int x, int y) | |||||
| if (fCallback != nullptr) | if (fCallback != nullptr) | ||||
| fCallback->imageButtonClicked(this, fCurButton); | fCallback->imageButtonClicked(this, fCurButton); | ||||
| //if (contains(x, y)) | |||||
| //{ | |||||
| // fCurImage = &fImageHover; | |||||
| // repaint(); | |||||
| //} | |||||
| #if 0 | |||||
| if (contains(ev.pos)) | |||||
| { | |||||
| fCurImage = &fImageHover; | |||||
| repaint(); | |||||
| } | |||||
| #endif | |||||
| fCurButton = -1; | fCurButton = -1; | ||||
| return true; | return true; | ||||
| } | } | ||||
| if (press && contains(x, y)) | |||||
| if (ev.press && contains(ev.pos)) | |||||
| { | { | ||||
| if (fCurImage != &fImageDown) | if (fCurImage != &fImageDown) | ||||
| { | { | ||||
| @@ -132,19 +134,19 @@ bool ImageButton::onMouse(int button, bool press, int x, int y) | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| fCurButton = button; | |||||
| fCurButton = ev.button; | |||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool ImageButton::onMotion(int x, int y) | |||||
| bool ImageButton::onMotion(const MotionEvent& ev) | |||||
| { | { | ||||
| if (fCurButton != -1) | if (fCurButton != -1) | ||||
| return true; | return true; | ||||
| if (contains(x, y)) | |||||
| if (contains(ev.pos)) | |||||
| { | { | ||||
| if (fCurImage != &fImageHover) | if (fCurImage != &fImageHover) | ||||
| { | { | ||||
| @@ -101,6 +101,12 @@ ImageKnob::ImageKnob(const ImageKnob& imageKnob) | |||||
| } | } | ||||
| } | } | ||||
| ImageKnob::~ImageKnob() | |||||
| { | |||||
| // delete old texture | |||||
| setRotationAngle(0); | |||||
| } | |||||
| int ImageKnob::getId() const noexcept | int ImageKnob::getId() const noexcept | ||||
| { | { | ||||
| return fId; | return fId; | ||||
| @@ -274,19 +280,19 @@ void ImageKnob::onDisplay() | |||||
| } | } | ||||
| } | } | ||||
| bool ImageKnob::onMouse(int button, bool press, int x, int y) | |||||
| bool ImageKnob::onMouse(const MouseEvent& ev) | |||||
| { | { | ||||
| if (button != 1) | |||||
| if (ev.button != 1) | |||||
| return false; | return false; | ||||
| if (press) | |||||
| if (ev.press) | |||||
| { | { | ||||
| if (! contains(x, y)) | |||||
| if (! contains(ev.pos)) | |||||
| return false; | return false; | ||||
| fDragging = true; | fDragging = true; | ||||
| fLastX = x; | |||||
| fLastY = y; | |||||
| fLastX = ev.pos.getX(); | |||||
| fLastY = ev.pos.getY(); | |||||
| if (fCallback != nullptr) | if (fCallback != nullptr) | ||||
| fCallback->imageKnobDragStarted(this); | fCallback->imageKnobDragStarted(this); | ||||
| @@ -305,7 +311,7 @@ bool ImageKnob::onMouse(int button, bool press, int x, int y) | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool ImageKnob::onMotion(int x, int y) | |||||
| bool ImageKnob::onMotion(const MotionEvent& ev) | |||||
| { | { | ||||
| if (! fDragging) | if (! fDragging) | ||||
| return false; | return false; | ||||
| @@ -315,18 +321,18 @@ bool ImageKnob::onMotion(int x, int y) | |||||
| if (fOrientation == ImageKnob::Horizontal) | if (fOrientation == ImageKnob::Horizontal) | ||||
| { | { | ||||
| if (int movX = x - fLastX) | |||||
| if (int movX = ev.pos.getX() - fLastX) | |||||
| { | { | ||||
| d = (getModifiers() & MODIFIER_SHIFT) ? 2000.0f : 200.0f; | |||||
| d = (ev.mod & MODIFIER_SHIFT) ? 2000.0f : 200.0f; | |||||
| value = fValueTmp + (float(fMaximum - fMinimum) / d * float(movX)); | value = fValueTmp + (float(fMaximum - fMinimum) / d * float(movX)); | ||||
| doVal = true; | doVal = true; | ||||
| } | } | ||||
| } | } | ||||
| else if (fOrientation == ImageKnob::Vertical) | else if (fOrientation == ImageKnob::Vertical) | ||||
| { | { | ||||
| if (int movY = fLastY - y) | |||||
| if (int movY = fLastY - ev.pos.getY()) | |||||
| { | { | ||||
| d = (getModifiers() & MODIFIER_SHIFT) ? 2000.0f : 200.0f; | |||||
| d = (ev.mod & MODIFIER_SHIFT) ? 2000.0f : 200.0f; | |||||
| value = fValueTmp + (float(fMaximum - fMinimum) / d * float(movY)); | value = fValueTmp + (float(fMaximum - fMinimum) / d * float(movY)); | ||||
| doVal = true; | doVal = true; | ||||
| } | } | ||||
| @@ -354,26 +360,12 @@ bool ImageKnob::onMotion(int x, int y) | |||||
| setValue(value, true); | setValue(value, true); | ||||
| fLastX = x; | |||||
| fLastY = y; | |||||
| fLastX = ev.pos.getX(); | |||||
| fLastY = ev.pos.getY(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| void ImageKnob::onReshape(int width, int height) | |||||
| { | |||||
| // if (fRotationAngle != 0) | |||||
| // glEnable(GL_TEXTURE_2D); | |||||
| Widget::onReshape(width, height); | |||||
| } | |||||
| void ImageKnob::onClose() | |||||
| { | |||||
| // delete old texture | |||||
| setRotationAngle(0); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| END_NAMESPACE_DGL | END_NAMESPACE_DGL | ||||
| @@ -222,17 +222,19 @@ void ImageSlider::onDisplay() | |||||
| fImage.drawAt(x, y); | fImage.drawAt(x, y); | ||||
| } | } | ||||
| bool ImageSlider::onMouse(int button, bool press, int x, int y) | |||||
| bool ImageSlider::onMouse(const MouseEvent& ev) | |||||
| { | { | ||||
| if (button != 1) | |||||
| if (ev.button != 1) | |||||
| return false; | return false; | ||||
| if (press) | |||||
| if (ev.press) | |||||
| { | { | ||||
| if (! fSliderArea.contains(x, y)) | |||||
| if (! fSliderArea.contains(ev.pos)) | |||||
| return false; | return false; | ||||
| float vper; | float vper; | ||||
| const int x = ev.pos.getX(); | |||||
| const int y = ev.pos.getY(); | |||||
| if (fStartPos.getY() == fEndPos.getY()) | if (fStartPos.getY() == fEndPos.getY()) | ||||
| { | { | ||||
| @@ -292,12 +294,14 @@ bool ImageSlider::onMouse(int button, bool press, int x, int y) | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool ImageSlider::onMotion(int x, int y) | |||||
| bool ImageSlider::onMotion(const MotionEvent& ev) | |||||
| { | { | ||||
| if (! fDragging) | if (! fDragging) | ||||
| return false; | return false; | ||||
| const bool horizontal = fStartPos.getY() == fEndPos.getY(); | 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)) | if ((horizontal && fSliderArea.containsX(x)) || (fSliderArea.containsY(y) && ! horizontal)) | ||||
| { | { | ||||
| @@ -58,111 +58,116 @@ void Widget::hide() | |||||
| setVisible(false); | setVisible(false); | ||||
| } | } | ||||
| int Widget::getX() const noexcept | |||||
| int Widget::getWidth() const noexcept | |||||
| { | { | ||||
| return fArea.getX(); | |||||
| return fArea.getWidth(); | |||||
| } | } | ||||
| int Widget::getY() const noexcept | |||||
| int Widget::getHeight() const noexcept | |||||
| { | { | ||||
| return fArea.getY(); | |||||
| return fArea.getHeight(); | |||||
| } | } | ||||
| const Point<int>& Widget::getPos() const noexcept | |||||
| const Size<int>& Widget::getSize() const noexcept | |||||
| { | { | ||||
| return fArea.getPos(); | |||||
| return fArea.getSize(); | |||||
| } | } | ||||
| void Widget::setX(int x) noexcept | |||||
| void Widget::setWidth(int width) noexcept | |||||
| { | { | ||||
| if (fArea.getX() == x) | |||||
| if (fArea.getWidth() == width) | |||||
| return; | return; | ||||
| fArea.setX(x); | |||||
| ResizeEvent ev; | |||||
| ev.oldSize = fArea.getSize(); | |||||
| ev.size = Size<int>(width, fArea.getHeight()); | |||||
| fArea.setWidth(width); | |||||
| onResize(ev); | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| } | } | ||||
| void Widget::setY(int y) noexcept | |||||
| void Widget::setHeight(int height) noexcept | |||||
| { | { | ||||
| if (fArea.getY() == y) | |||||
| if (fArea.getHeight() == height) | |||||
| return; | return; | ||||
| fArea.setY(y); | |||||
| ResizeEvent ev; | |||||
| ev.oldSize = fArea.getSize(); | |||||
| ev.size = Size<int>(fArea.getWidth(), height); | |||||
| fArea.setHeight(height); | |||||
| onResize(ev); | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| } | } | ||||
| void Widget::setPos(int x, int y) noexcept | |||||
| void Widget::setSize(int width, int height) noexcept | |||||
| { | { | ||||
| setPos(Point<int>(x, y)); | |||||
| setSize(Size<int>(width, height)); | |||||
| } | } | ||||
| void Widget::setPos(const Point<int>& pos) noexcept | |||||
| void Widget::setSize(const Size<int>& size) noexcept | |||||
| { | { | ||||
| if (fArea.getPos() == pos) | |||||
| if (fArea.getSize() == size) | |||||
| return; | return; | ||||
| fArea.setPos(pos); | |||||
| ResizeEvent ev; | |||||
| ev.oldSize = fArea.getSize(); | |||||
| ev.size = size; | |||||
| fArea.setSize(size); | |||||
| onResize(ev); | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| } | } | ||||
| int Widget::getWidth() const noexcept | |||||
| int Widget::getAbsoluteX() const noexcept | |||||
| { | { | ||||
| return fArea.getWidth(); | |||||
| return fArea.getX(); | |||||
| } | } | ||||
| int Widget::getHeight() const noexcept | |||||
| int Widget::getAbsoluteY() const noexcept | |||||
| { | { | ||||
| return fArea.getHeight(); | |||||
| return fArea.getY(); | |||||
| } | } | ||||
| const Size<int>& Widget::getSize() const noexcept | |||||
| const Point<int>& Widget::getAbsolutePos() const noexcept | |||||
| { | { | ||||
| return fArea.getSize(); | |||||
| return fArea.getPos(); | |||||
| } | } | ||||
| void Widget::setWidth(int width) noexcept | |||||
| void Widget::setAbsoluteX(int x) noexcept | |||||
| { | { | ||||
| if (fArea.getWidth() == width) | |||||
| if (fArea.getX() == x) | |||||
| return; | return; | ||||
| fArea.setWidth(width); | |||||
| fArea.setX(x); | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| onReshape(width, fArea.getHeight()); | |||||
| } | } | ||||
| void Widget::setHeight(int height) noexcept | |||||
| void Widget::setAbsoluteY(int y) noexcept | |||||
| { | { | ||||
| if (fArea.getHeight() == height) | |||||
| if (fArea.getY() == y) | |||||
| return; | return; | ||||
| fArea.setHeight(height); | |||||
| fArea.setY(y); | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| onReshape(fArea.getWidth(), height); | |||||
| } | } | ||||
| void Widget::setSize(int width, int height) noexcept | |||||
| void Widget::setAbsolutePos(int x, int y) noexcept | |||||
| { | { | ||||
| setSize(Size<int>(width, height)); | |||||
| setAbsolutePos(Point<int>(x, y)); | |||||
| } | } | ||||
| void Widget::setSize(const Size<int>& size) noexcept | |||||
| void Widget::setAbsolutePos(const Point<int>& pos) noexcept | |||||
| { | { | ||||
| if (fArea.getSize() == size) | |||||
| if (fArea.getPos() == pos) | |||||
| return; | return; | ||||
| fArea.setSize(size); | |||||
| fArea.setPos(pos); | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| onReshape(fArea.getWidth(), fArea.getHeight()); | |||||
| } | |||||
| uint Widget::getEventTimestamp() const noexcept | |||||
| { | |||||
| return fParent.getEventTimestamp(); | |||||
| } | |||||
| int Widget::getModifiers() const noexcept | |||||
| { | |||||
| return fParent.getModifiers(); | |||||
| } | } | ||||
| App& Widget::getParentApp() const noexcept | App& Widget::getParentApp() const noexcept | ||||
| @@ -190,32 +195,32 @@ void Widget::repaint() noexcept | |||||
| fParent.repaint(); | fParent.repaint(); | ||||
| } | } | ||||
| bool Widget::onKeyboard(bool, uint) | |||||
| bool Widget::onKeyboard(const KeyboardEvent&) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool Widget::onMouse(int, bool, int, int) | |||||
| bool Widget::onSpecial(const SpecialEvent&) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool Widget::onMotion(int, int) | |||||
| bool Widget::onMouse(const MouseEvent&) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool Widget::onScroll(int, int, float, float) | |||||
| bool Widget::onMotion(const MotionEvent&) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool Widget::onSpecial(bool, Key) | |||||
| bool Widget::onScroll(const ScrollEvent&) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| void Widget::onReshape(int, int) | |||||
| void Widget::onResize(const ResizeEvent&) | |||||
| { | { | ||||
| } | } | ||||
| @@ -575,7 +575,7 @@ struct Window::PrivateData { | |||||
| if (widget->isVisible()) | if (widget->isVisible()) | ||||
| { | { | ||||
| glViewport(widget->getX(), -widget->getY(), fView->width, fView->height); | |||||
| glViewport(widget->getAbsoluteX(), -widget->getAbsoluteY(), fView->width, fView->height); | |||||
| widget->onDisplay(); | widget->onDisplay(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -590,75 +590,108 @@ struct Window::PrivateData { | |||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return fModal.childFocus->focus(); | return fModal.childFocus->focus(); | ||||
| Widget::KeyboardEvent ev; | |||||
| ev.press = press; | |||||
| ev.key = key; | |||||
| ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||||
| ev.time = puglGetEventTimestamp(fView); | |||||
| FOR_EACH_WIDGET_INV(rit) | FOR_EACH_WIDGET_INV(rit) | ||||
| { | { | ||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onKeyboard(press, key)) | |||||
| if (widget->isVisible() && widget->onKeyboard(ev)) | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| void onMouse(const int button, const bool press, const int x, const int y) | |||||
| void onSpecial(const bool press, const Key key) | |||||
| { | { | ||||
| DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y); | |||||
| DBGp("PUGL: onSpecial : %i %i\n", press, key); | |||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return fModal.childFocus->focus(); | return fModal.childFocus->focus(); | ||||
| Widget::SpecialEvent ev; | |||||
| ev.press = press; | |||||
| ev.key = key; | |||||
| ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||||
| ev.time = puglGetEventTimestamp(fView); | |||||
| FOR_EACH_WIDGET_INV(rit) | FOR_EACH_WIDGET_INV(rit) | ||||
| { | { | ||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onMouse(button, press, x-widget->getX(), y-widget->getY())) | |||||
| if (widget->isVisible() && widget->onSpecial(ev)) | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| void onMotion(const int x, const int y) | |||||
| void onMouse(const int button, const bool press, const int x, const int y) | |||||
| { | { | ||||
| DBGp("PUGL: onMotion : %i %i\n", x, y); | |||||
| DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y); | |||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return; | |||||
| return fModal.childFocus->focus(); | |||||
| Widget::MouseEvent ev; | |||||
| ev.button = button; | |||||
| ev.press = press; | |||||
| ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||||
| ev.time = puglGetEventTimestamp(fView); | |||||
| FOR_EACH_WIDGET_INV(rit) | FOR_EACH_WIDGET_INV(rit) | ||||
| { | { | ||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onMotion(x-widget->getX(), y-widget->getY())) | |||||
| ev.pos = Point<int>(x-widget->getAbsoluteX(), y-widget->getAbsoluteY()); | |||||
| if (widget->isVisible() && widget->onMouse(ev)) | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| void onScroll(const int x, const int y, const float dx, const float dy) | |||||
| void onMotion(const int x, const int y) | |||||
| { | { | ||||
| DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy); | |||||
| DBGp("PUGL: onMotion : %i %i\n", x, y); | |||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return; | return; | ||||
| Widget::MotionEvent ev; | |||||
| ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||||
| ev.time = puglGetEventTimestamp(fView); | |||||
| FOR_EACH_WIDGET_INV(rit) | FOR_EACH_WIDGET_INV(rit) | ||||
| { | { | ||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onScroll(x-widget->getX(), y-widget->getY(), dx, dy)) | |||||
| ev.pos = Point<int>(x-widget->getAbsoluteX(), y-widget->getAbsoluteY()); | |||||
| if (widget->isVisible() && widget->onMotion(ev)) | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| void onSpecial(const bool press, const Key key) | |||||
| void onScroll(const int x, const int y, const float dx, const float dy) | |||||
| { | { | ||||
| DBGp("PUGL: onSpecial : %i %i\n", press, key); | |||||
| DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy); | |||||
| if (fModal.childFocus != nullptr) | if (fModal.childFocus != nullptr) | ||||
| return fModal.childFocus->focus(); | |||||
| return; | |||||
| Widget::ScrollEvent ev; | |||||
| ev._ = Point<float>(dx, dy); | |||||
| ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||||
| ev.time = puglGetEventTimestamp(fView); | |||||
| FOR_EACH_WIDGET_INV(rit) | FOR_EACH_WIDGET_INV(rit) | ||||
| { | { | ||||
| Widget* const widget(*rit); | Widget* const widget(*rit); | ||||
| if (widget->isVisible() && widget->onSpecial(press, key)) | |||||
| ev.pos = Point<int>(x-widget->getAbsoluteX(), y-widget->getAbsoluteY()); | |||||
| if (widget->isVisible() && widget->onScroll(ev)) | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -728,7 +761,7 @@ struct Window::PrivateData { | |||||
| bool fNeedsIdle; | bool fNeedsIdle; | ||||
| id xWindow; | id xWindow; | ||||
| #else | #else | ||||
| char _dummy; | |||||
| char _dummy; | |||||
| #endif | #endif | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -746,6 +779,11 @@ struct Window::PrivateData { | |||||
| handlePtr->onKeyboard(press, key); | handlePtr->onKeyboard(press, key); | ||||
| } | } | ||||
| static void onSpecialCallback(PuglView* view, bool press, PuglKey key) | |||||
| { | |||||
| handlePtr->onSpecial(press, static_cast<Key>(key)); | |||||
| } | |||||
| static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) | static void onMouseCallback(PuglView* view, int button, bool press, int x, int y) | ||||
| { | { | ||||
| handlePtr->onMouse(button, press, x, y); | handlePtr->onMouse(button, press, x, y); | ||||
| @@ -761,11 +799,6 @@ struct Window::PrivateData { | |||||
| handlePtr->onScroll(x, y, dx, dy); | handlePtr->onScroll(x, y, dx, dy); | ||||
| } | } | ||||
| static void onSpecialCallback(PuglView* view, bool press, PuglKey key) | |||||
| { | |||||
| handlePtr->onSpecial(press, static_cast<Key>(key)); | |||||
| } | |||||
| static void onReshapeCallback(PuglView* view, int width, int height) | static void onReshapeCallback(PuglView* view, int width, int height) | ||||
| { | { | ||||
| handlePtr->onReshape(width, height); | handlePtr->onReshape(width, height); | ||||
| @@ -888,16 +921,6 @@ App& Window::getApp() const noexcept | |||||
| return pData->fApp; | return pData->fApp; | ||||
| } | } | ||||
| int Window::getModifiers() const noexcept | |||||
| { | |||||
| return puglGetModifiers(pData->fView); | |||||
| } | |||||
| uint Window::getEventTimestamp() const noexcept | |||||
| { | |||||
| return puglGetEventTimestamp(pData->fView); | |||||
| } | |||||
| intptr_t Window::getWindowId() const noexcept | intptr_t Window::getWindowId() const noexcept | ||||
| { | { | ||||
| return puglGetNativeWindow(pData->fView); | return puglGetNativeWindow(pData->fView); | ||||
| @@ -946,10 +969,6 @@ void Window::onDisplayAfter() | |||||
| { | { | ||||
| } | } | ||||
| void Window::onClose() | |||||
| { | |||||
| } | |||||
| void Window::onReshape(int width, int height) | void Window::onReshape(int width, int height) | ||||
| { | { | ||||
| glEnable(GL_BLEND); | glEnable(GL_BLEND); | ||||
| @@ -962,6 +981,10 @@ void Window::onReshape(int width, int height) | |||||
| glLoadIdentity(); | glLoadIdentity(); | ||||
| } | } | ||||
| void Window::onClose() | |||||
| { | |||||
| } | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| END_NAMESPACE_DGL | END_NAMESPACE_DGL | ||||
| @@ -51,7 +51,7 @@ | |||||
| # define PROPER_CPP11_SUPPORT | # define PROPER_CPP11_SUPPORT | ||||
| #elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) | #elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) | ||||
| # define PROPER_CPP11_SUPPORT | # define PROPER_CPP11_SUPPORT | ||||
| # if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || ! __has_extension(cxx_override_control) | |||||
| # if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) && ! __has_extension(cxx_override_control) | |||||
| # define override // gcc4.7+ only | # define override // gcc4.7+ only | ||||
| # define final // gcc4.7+ only | # define final // gcc4.7+ only | ||||
| # endif | # endif | ||||
| @@ -280,11 +280,11 @@ public: | |||||
| { | { | ||||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, false); | DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, false); | ||||
| glApp.idle(); | |||||
| if (glWindow.isReady()) | if (glWindow.isReady()) | ||||
| fUi->d_uiIdle(); | fUi->d_uiIdle(); | ||||
| glApp.idle(); | |||||
| return ! glApp.isQuiting(); | return ! glApp.isQuiting(); | ||||
| } | } | ||||