@@ -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(); | |||
} | |||