| @@ -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 | |||
| { | |||
| public: | |||
| /** | |||
| Constructor for a null Image. | |||
| */ | |||
| 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; | |||
| /** | |||
| 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; | |||
| /** | |||
| Constructor using another image data. | |||
| */ | |||
| Image(const Image& image) noexcept; | |||
| /** | |||
| Destructor. | |||
| */ | |||
| ~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; | |||
| /** | |||
| 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; | |||
| /** | |||
| Check if this image is valid. | |||
| */ | |||
| bool isValid() const noexcept; | |||
| /** | |||
| Get width. | |||
| */ | |||
| int getWidth() const noexcept; | |||
| /** | |||
| Get height. | |||
| */ | |||
| int getHeight() const noexcept; | |||
| /** | |||
| Get size. | |||
| */ | |||
| const Size<int>& getSize() const noexcept; | |||
| /** | |||
| Get the raw image data. | |||
| */ | |||
| const char* getRawData() const noexcept; | |||
| /** | |||
| Get the image format. | |||
| */ | |||
| GLenum getFormat() const noexcept; | |||
| /** | |||
| Get the image type. | |||
| */ | |||
| GLenum getType() const noexcept; | |||
| /** | |||
| Draw this image at (0, 0) point. | |||
| */ | |||
| void draw(); | |||
| /** | |||
| Draw this image at (x, y) point. | |||
| */ | |||
| void drawAt(int x, int y); | |||
| /** | |||
| Draw this image at position @a pos. | |||
| */ | |||
| void drawAt(const Point<int>& pos); | |||
| Image& operator=(const Image& image) noexcept; | |||
| @@ -36,8 +36,8 @@ public: | |||
| protected: | |||
| 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: | |||
| Image fImgBackground; | |||
| @@ -44,8 +44,8 @@ public: | |||
| protected: | |||
| 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: | |||
| Image fImageNormal; | |||
| @@ -44,6 +44,7 @@ public: | |||
| 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(const ImageKnob& imageKnob); | |||
| ~ImageKnob() override; | |||
| int getId() const noexcept; | |||
| void setId(int id) noexcept; | |||
| @@ -60,10 +61,9 @@ public: | |||
| protected: | |||
| 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: | |||
| Image fImage; | |||
| @@ -59,8 +59,8 @@ public: | |||
| protected: | |||
| 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: | |||
| Image fImage; | |||
| @@ -22,45 +22,222 @@ | |||
| START_NAMESPACE_DGL | |||
| // ----------------------------------------------------------------------- | |||
| // Forward class names | |||
| class App; | |||
| 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 | |||
| { | |||
| 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); | |||
| /** | |||
| Destructor. | |||
| */ | |||
| virtual ~Widget(); | |||
| /** | |||
| Check if this widget is visible within its parent window. | |||
| Invisible widgets do not receive events except resize. | |||
| */ | |||
| bool isVisible() const noexcept; | |||
| /** | |||
| Set widget visible (or not) according to @a yesNo. | |||
| */ | |||
| void setVisible(bool yesNo); | |||
| /** | |||
| Show widget. | |||
| This is the same as calling setVisible(true). | |||
| */ | |||
| 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; | |||
| /** | |||
| Get height. | |||
| */ | |||
| int getHeight() const noexcept; | |||
| /** | |||
| Get size. | |||
| */ | |||
| const Size<int>& getSize() const noexcept; | |||
| // virtual needed by cairo | |||
| /** | |||
| Set width. | |||
| */ | |||
| virtual void setWidth(int width) noexcept; | |||
| /** | |||
| Set height. | |||
| */ | |||
| virtual void setHeight(int height) noexcept; | |||
| /** | |||
| Set size using @a width and @a height values. | |||
| */ | |||
| virtual void setSize(int width, int height) noexcept; | |||
| /** | |||
| Set size. | |||
| */ | |||
| 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; | |||
| /** | |||
| @@ -73,16 +250,51 @@ public: | |||
| */ | |||
| bool contains(const Point<int>& pos) const noexcept; | |||
| /** | |||
| Tell this widget's window to repaint itself. | |||
| */ | |||
| void repaint() noexcept; | |||
| protected: | |||
| /** | |||
| A function called to draw the view contents with OpenGL. | |||
| */ | |||
| 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: | |||
| Window& fParent; | |||
| @@ -59,8 +59,6 @@ public: | |||
| void setTransientWinId(intptr_t winId); | |||
| App& getApp() const noexcept; | |||
| uint getEventTimestamp() const noexcept; | |||
| int getModifiers() const noexcept; | |||
| intptr_t getWindowId() const noexcept; | |||
| void addIdleCallback(IdleCallback* const callback); | |||
| @@ -69,8 +67,8 @@ public: | |||
| protected: | |||
| virtual void onDisplayBefore(); | |||
| virtual void onDisplayAfter(); | |||
| virtual void onClose(); | |||
| virtual void onReshape(int width, int height); | |||
| virtual void onClose(); | |||
| private: | |||
| struct PrivateData; | |||
| @@ -54,9 +54,9 @@ void ImageAboutWindow::onDisplay() | |||
| 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(); | |||
| return true; | |||
| @@ -65,9 +65,9 @@ bool ImageAboutWindow::onMouse(int, bool press, int, int) | |||
| 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(); | |||
| return true; | |||
| @@ -91,12 +91,12 @@ void ImageButton::setCallback(Callback* callback) noexcept | |||
| 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) | |||
| { | |||
| @@ -104,7 +104,7 @@ bool ImageButton::onMouse(int button, bool press, int x, int y) | |||
| repaint(); | |||
| } | |||
| if (! contains(x, y)) | |||
| if (! contains(ev.pos)) | |||
| { | |||
| fCurButton = -1; | |||
| return false; | |||
| @@ -113,18 +113,20 @@ bool ImageButton::onMouse(int button, bool press, int x, int y) | |||
| if (fCallback != nullptr) | |||
| fCallback->imageButtonClicked(this, fCurButton); | |||
| //if (contains(x, y)) | |||
| //{ | |||
| // fCurImage = &fImageHover; | |||
| // repaint(); | |||
| //} | |||
| #if 0 | |||
| if (contains(ev.pos)) | |||
| { | |||
| fCurImage = &fImageHover; | |||
| repaint(); | |||
| } | |||
| #endif | |||
| fCurButton = -1; | |||
| return true; | |||
| } | |||
| if (press && contains(x, y)) | |||
| if (ev.press && contains(ev.pos)) | |||
| { | |||
| if (fCurImage != &fImageDown) | |||
| { | |||
| @@ -132,19 +134,19 @@ bool ImageButton::onMouse(int button, bool press, int x, int y) | |||
| repaint(); | |||
| } | |||
| fCurButton = button; | |||
| fCurButton = ev.button; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| bool ImageButton::onMotion(int x, int y) | |||
| bool ImageButton::onMotion(const MotionEvent& ev) | |||
| { | |||
| if (fCurButton != -1) | |||
| return true; | |||
| if (contains(x, y)) | |||
| if (contains(ev.pos)) | |||
| { | |||
| if (fCurImage != &fImageHover) | |||
| { | |||
| @@ -101,6 +101,12 @@ ImageKnob::ImageKnob(const ImageKnob& imageKnob) | |||
| } | |||
| } | |||
| ImageKnob::~ImageKnob() | |||
| { | |||
| // delete old texture | |||
| setRotationAngle(0); | |||
| } | |||
| int ImageKnob::getId() const noexcept | |||
| { | |||
| 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; | |||
| if (press) | |||
| if (ev.press) | |||
| { | |||
| if (! contains(x, y)) | |||
| if (! contains(ev.pos)) | |||
| return false; | |||
| fDragging = true; | |||
| fLastX = x; | |||
| fLastY = y; | |||
| fLastX = ev.pos.getX(); | |||
| fLastY = ev.pos.getY(); | |||
| if (fCallback != nullptr) | |||
| fCallback->imageKnobDragStarted(this); | |||
| @@ -305,7 +311,7 @@ bool ImageKnob::onMouse(int button, bool press, int x, int y) | |||
| return false; | |||
| } | |||
| bool ImageKnob::onMotion(int x, int y) | |||
| bool ImageKnob::onMotion(const MotionEvent& ev) | |||
| { | |||
| if (! fDragging) | |||
| return false; | |||
| @@ -315,18 +321,18 @@ bool ImageKnob::onMotion(int x, int y) | |||
| 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)); | |||
| doVal = true; | |||
| } | |||
| } | |||
| 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)); | |||
| doVal = true; | |||
| } | |||
| @@ -354,26 +360,12 @@ bool ImageKnob::onMotion(int x, int y) | |||
| setValue(value, true); | |||
| fLastX = x; | |||
| fLastY = y; | |||
| fLastX = ev.pos.getX(); | |||
| fLastY = ev.pos.getY(); | |||
| 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 | |||
| @@ -222,17 +222,19 @@ void ImageSlider::onDisplay() | |||
| 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; | |||
| if (press) | |||
| if (ev.press) | |||
| { | |||
| if (! fSliderArea.contains(x, y)) | |||
| 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()) | |||
| { | |||
| @@ -292,12 +294,14 @@ bool ImageSlider::onMouse(int button, bool press, int x, int y) | |||
| return false; | |||
| } | |||
| bool ImageSlider::onMotion(int x, int y) | |||
| 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)) | |||
| { | |||
| @@ -58,111 +58,116 @@ void Widget::hide() | |||
| 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; | |||
| fArea.setX(x); | |||
| ResizeEvent ev; | |||
| ev.oldSize = fArea.getSize(); | |||
| ev.size = Size<int>(width, fArea.getHeight()); | |||
| fArea.setWidth(width); | |||
| onResize(ev); | |||
| fParent.repaint(); | |||
| } | |||
| void Widget::setY(int y) noexcept | |||
| void Widget::setHeight(int height) noexcept | |||
| { | |||
| if (fArea.getY() == y) | |||
| if (fArea.getHeight() == height) | |||
| return; | |||
| fArea.setY(y); | |||
| ResizeEvent ev; | |||
| ev.oldSize = fArea.getSize(); | |||
| ev.size = Size<int>(fArea.getWidth(), height); | |||
| fArea.setHeight(height); | |||
| onResize(ev); | |||
| 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; | |||
| fArea.setPos(pos); | |||
| ResizeEvent ev; | |||
| ev.oldSize = fArea.getSize(); | |||
| ev.size = size; | |||
| fArea.setSize(size); | |||
| onResize(ev); | |||
| 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; | |||
| fArea.setWidth(width); | |||
| fArea.setX(x); | |||
| 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; | |||
| fArea.setHeight(height); | |||
| fArea.setY(y); | |||
| 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; | |||
| fArea.setSize(size); | |||
| fArea.setPos(pos); | |||
| 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 | |||
| @@ -190,32 +195,32 @@ void Widget::repaint() noexcept | |||
| fParent.repaint(); | |||
| } | |||
| bool Widget::onKeyboard(bool, uint) | |||
| bool Widget::onKeyboard(const KeyboardEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool Widget::onMouse(int, bool, int, int) | |||
| bool Widget::onSpecial(const SpecialEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool Widget::onMotion(int, int) | |||
| bool Widget::onMouse(const MouseEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool Widget::onScroll(int, int, float, float) | |||
| bool Widget::onMotion(const MotionEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| bool Widget::onSpecial(bool, Key) | |||
| bool Widget::onScroll(const ScrollEvent&) | |||
| { | |||
| return false; | |||
| } | |||
| void Widget::onReshape(int, int) | |||
| void Widget::onResize(const ResizeEvent&) | |||
| { | |||
| } | |||
| @@ -575,7 +575,7 @@ struct Window::PrivateData { | |||
| if (widget->isVisible()) | |||
| { | |||
| glViewport(widget->getX(), -widget->getY(), fView->width, fView->height); | |||
| glViewport(widget->getAbsoluteX(), -widget->getAbsoluteY(), fView->width, fView->height); | |||
| widget->onDisplay(); | |||
| } | |||
| } | |||
| @@ -590,75 +590,108 @@ struct Window::PrivateData { | |||
| if (fModal.childFocus != nullptr) | |||
| 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) | |||
| { | |||
| Widget* const widget(*rit); | |||
| if (widget->isVisible() && widget->onKeyboard(press, key)) | |||
| if (widget->isVisible() && widget->onKeyboard(ev)) | |||
| 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) | |||
| 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) | |||
| { | |||
| Widget* const widget(*rit); | |||
| if (widget->isVisible() && widget->onMouse(button, press, x-widget->getX(), y-widget->getY())) | |||
| if (widget->isVisible() && widget->onSpecial(ev)) | |||
| 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) | |||
| 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) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| 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) | |||
| return; | |||
| Widget::MotionEvent ev; | |||
| ev.mod = static_cast<Modifier>(puglGetModifiers(fView)); | |||
| ev.time = puglGetEventTimestamp(fView); | |||
| FOR_EACH_WIDGET_INV(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; | |||
| } | |||
| } | |||
| 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) | |||
| 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) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| @@ -728,7 +761,7 @@ struct Window::PrivateData { | |||
| bool fNeedsIdle; | |||
| id xWindow; | |||
| #else | |||
| char _dummy; | |||
| char _dummy; | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| @@ -746,6 +779,11 @@ struct Window::PrivateData { | |||
| 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) | |||
| { | |||
| handlePtr->onMouse(button, press, x, y); | |||
| @@ -761,11 +799,6 @@ struct Window::PrivateData { | |||
| 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) | |||
| { | |||
| handlePtr->onReshape(width, height); | |||
| @@ -888,16 +921,6 @@ App& Window::getApp() const noexcept | |||
| 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 | |||
| { | |||
| return puglGetNativeWindow(pData->fView); | |||
| @@ -946,10 +969,6 @@ void Window::onDisplayAfter() | |||
| { | |||
| } | |||
| void Window::onClose() | |||
| { | |||
| } | |||
| void Window::onReshape(int width, int height) | |||
| { | |||
| glEnable(GL_BLEND); | |||
| @@ -962,6 +981,10 @@ void Window::onReshape(int width, int height) | |||
| glLoadIdentity(); | |||
| } | |||
| void Window::onClose() | |||
| { | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| END_NAMESPACE_DGL | |||
| @@ -51,7 +51,7 @@ | |||
| # define PROPER_CPP11_SUPPORT | |||
| #elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) | |||
| # 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 final // gcc4.7+ only | |||
| # endif | |||
| @@ -280,11 +280,11 @@ public: | |||
| { | |||
| DISTRHO_SAFE_ASSERT_RETURN(fUi != nullptr, false); | |||
| glApp.idle(); | |||
| if (glWindow.isReady()) | |||
| fUi->d_uiIdle(); | |||
| glApp.idle(); | |||
| return ! glApp.isQuiting(); | |||
| } | |||