summaryrefslogtreecommitdiff
path: root/plugingui
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2017-02-12 11:07:22 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2017-02-12 11:07:22 +0100
commitcec1d9ea562e3d52c98f1219db5e186943f2f0d6 (patch)
tree3a66ff06ef16cce96e215644032e6c9fac2cbe8a /plugingui
parentdc33f15a6b968139779c2b7d2003d3ef6e7d5748 (diff)
Refactor/introduce widget and windiow redraw/dirty mechanism to eradicate unnecessary rendering passes during event handling.
Diffstat (limited to 'plugingui')
-rw-r--r--plugingui/button.cc10
-rw-r--r--plugingui/canvas.h8
-rw-r--r--plugingui/checkbox.cc12
-rw-r--r--plugingui/combobox.cc8
-rw-r--r--plugingui/eventhandler.cc92
-rw-r--r--plugingui/eventhandler.h4
-rw-r--r--plugingui/knob.cc2
-rw-r--r--plugingui/label.cc2
-rw-r--r--plugingui/layout.h8
-rw-r--r--plugingui/led.cc2
-rw-r--r--plugingui/lineedit.cc6
-rw-r--r--plugingui/listboxbasic.cc14
-rw-r--r--plugingui/mainwindow.cc6
-rw-r--r--plugingui/nativewindow.h4
-rw-r--r--plugingui/nativewindow_win32.cc5
-rw-r--r--plugingui/nativewindow_win32.h1
-rw-r--r--plugingui/nativewindow_x11.cc23
-rw-r--r--plugingui/nativewindow_x11.h1
-rw-r--r--plugingui/painter.cc19
-rw-r--r--plugingui/painter.h14
-rw-r--r--plugingui/pixelbuffer.cc2
-rw-r--r--plugingui/pixelbuffer.h2
-rw-r--r--plugingui/progressbar.cc6
-rw-r--r--plugingui/scrollbar.cc6
-rw-r--r--plugingui/slider.cc8
-rw-r--r--plugingui/textedit.cc4
-rw-r--r--plugingui/widget.cc97
-rw-r--r--plugingui/widget.h34
-rw-r--r--plugingui/window.cc111
-rw-r--r--plugingui/window.h22
30 files changed, 194 insertions, 339 deletions
diff --git a/plugingui/button.cc b/plugingui/button.cc
index 29d3deb..fb25390 100644
--- a/plugingui/button.cc
+++ b/plugingui/button.cc
@@ -57,14 +57,14 @@ void Button::buttonEvent(ButtonEvent* buttonEvent)
draw_state = down;
button_state = down;
in_button = true;
- repaintEvent(nullptr);
+ redraw();
}
if(buttonEvent->direction == Direction::up)
{
draw_state = up;
button_state = up;
- repaintEvent(nullptr);
+ redraw();
if(in_button)
{
clicked();
@@ -110,7 +110,7 @@ void Button::repaintEvent(RepaintEvent* repaintEvent)
void Button::setText(const std::string& text)
{
this->text = text;
- repaintEvent(nullptr);
+ redraw();
}
void Button::mouseLeaveEvent()
@@ -119,7 +119,7 @@ void Button::mouseLeaveEvent()
if(button_state == down)
{
draw_state = up;
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -129,7 +129,7 @@ void Button::mouseEnterEvent()
if(button_state == down)
{
draw_state = down;
- repaintEvent(nullptr);
+ redraw();
}
}
diff --git a/plugingui/canvas.h b/plugingui/canvas.h
index cafe483..2326f0e 100644
--- a/plugingui/canvas.h
+++ b/plugingui/canvas.h
@@ -39,14 +39,6 @@ public:
//! @returns a reference to the pixel buffer.
virtual PixelBufferAlpha& GetPixelBuffer() = 0;
-
- //! Signal the beginning of a paint operation.
- virtual void beginPaint() = 0;
-
- //! Signal the ending of a paint operation
- //! This might trigger a redraw operation.
- virtual void endPaint() = 0;
-
};
} // GUI::
diff --git a/plugingui/checkbox.cc b/plugingui/checkbox.cc
index bada623..2a17635 100644
--- a/plugingui/checkbox.cc
+++ b/plugingui/checkbox.cc
@@ -62,13 +62,13 @@ void CheckBox::buttonEvent(ButtonEvent* buttonEvent)
middle = true;
}
- repaintEvent(nullptr);
+ redraw();
}
void CheckBox::setText(std::string text)
{
_text = text;
- repaintEvent(nullptr);
+ redraw();
}
void CheckBox::keyEvent(KeyEvent* keyEvent)
@@ -85,7 +85,7 @@ void CheckBox::keyEvent(KeyEvent* keyEvent)
middle = true;
}
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -129,7 +129,7 @@ void CheckBox::mouseLeaveEvent()
if(buttonDown)
{
middle = false;
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -139,7 +139,7 @@ void CheckBox::mouseEnterEvent()
if(buttonDown)
{
middle = true;
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -152,7 +152,7 @@ void CheckBox::internalSetChecked(bool checked)
state = checked;
stateChangedNotifier(state);
- repaintEvent(nullptr);
+ redraw();
}
} // GUI::
diff --git a/plugingui/combobox.cc b/plugingui/combobox.cc
index ffbde88..82fc6d1 100644
--- a/plugingui/combobox.cc
+++ b/plugingui/combobox.cc
@@ -65,13 +65,13 @@ void ComboBox::addItem(std::string name, std::string value)
void ComboBox::clear()
{
listbox.clear();
- repaintEvent(nullptr);
+ redraw();
}
bool ComboBox::selectItem(int index)
{
listbox.selectItem(index);
- repaintEvent(nullptr);
+ redraw();
return true;
}
@@ -143,7 +143,7 @@ void ComboBox::scrollEvent(ScrollEvent* scrollEvent)
{
scroll_offset = (items.size() - 1);
}
- repaintEvent(nullptr);
+ redraw();
*/
}
@@ -203,7 +203,7 @@ void ComboBox::keyEvent(KeyEvent* keyEvent)
break;
}
- repaintEvent(nullptr);
+ redraw();
*/
}
diff --git a/plugingui/eventhandler.cc b/plugingui/eventhandler.cc
index aded993..2cdb6b1 100644
--- a/plugingui/eventhandler.cc
+++ b/plugingui/eventhandler.cc
@@ -56,21 +56,8 @@ std::shared_ptr<Event> EventHandler::getNextEvent()
return event;
}
-std::shared_ptr<Event> EventHandler::peekNextEvent()
-{
- if(events.empty())
- {
- return nullptr;
- }
-
- auto event = events.front();
- return event;
-}
-
void EventHandler::processEvents()
{
- Painter p(window); // Make sure we only redraw buffer one time.
-
events = nativeWindow.getEvents();
while(hasEvent())
@@ -96,26 +83,6 @@ void EventHandler::processEvents()
case EventType::resize:
{
- while(true)
- {
- if(!hasEvent())
- {
- break;
- }
-
- auto peekEvent = peekNextEvent();
- if(!peekEvent)
- {
- break;
- }
- if(peekEvent->type() != EventType::resize)
- {
- break;
- }
-
- event = getNextEvent();
- }
-
auto resizeEvent = static_cast<ResizeEvent*>(event.get());
if((resizeEvent->width != window.width()) ||
(resizeEvent->height != window.height()))
@@ -134,16 +101,6 @@ void EventHandler::processEvents()
break;
}
- auto peekEvent = peekNextEvent();
- if(!peekEvent)
- {
- break;
- }
- if(peekEvent->type() != EventType::mouseMove)
- {
- break;
- }
-
event = getNextEvent();
}
@@ -171,8 +128,8 @@ void EventHandler::processEvents()
if(window.buttonDownFocus())
{
auto widget = window.buttonDownFocus();
- moveEvent->x -= widget->windowX();
- moveEvent->y -= widget->windowY();
+ moveEvent->x -= widget->translateToWindowX();
+ moveEvent->y -= widget->translateToWindowY();
window.buttonDownFocus()->mouseMoveEvent(moveEvent);
break;
@@ -180,8 +137,8 @@ void EventHandler::processEvents()
if(widget)
{
- moveEvent->x -= widget->windowX();
- moveEvent->y -= widget->windowY();
+ moveEvent->x -= widget->translateToWindowX();
+ moveEvent->y -= widget->translateToWindowY();
widget->mouseMoveEvent(moveEvent);
}
}
@@ -206,8 +163,8 @@ void EventHandler::processEvents()
if(buttonEvent->direction == Direction::up)
{
auto widget = window.buttonDownFocus();
- buttonEvent->x -= widget->windowX();
- buttonEvent->y -= widget->windowY();
+ buttonEvent->x -= widget->translateToWindowX();
+ buttonEvent->y -= widget->translateToWindowY();
widget->buttonEvent(buttonEvent);
window.setButtonDownFocus(nullptr);
@@ -217,8 +174,8 @@ void EventHandler::processEvents()
if(widget)
{
- buttonEvent->x -= widget->windowX();
- buttonEvent->y -= widget->windowY();
+ buttonEvent->x -= widget->translateToWindowX();
+ buttonEvent->y -= widget->translateToWindowY();
widget->buttonEvent(buttonEvent);
@@ -238,38 +195,13 @@ void EventHandler::processEvents()
case EventType::scroll:
{
- int delta = 0;
- while(true)
- {
- if(!hasEvent())
- {
- break;
- }
-
- auto peekEvent = peekNextEvent();
- if(!peekEvent)
- {
- break;
- }
- if(peekEvent->type() != EventType::scroll)
- {
- break;
- }
-
- auto scrollEvent = static_cast<ScrollEvent*>(event.get());
- delta += scrollEvent->delta;
-
- event = getNextEvent();
- }
-
auto scrollEvent = static_cast<ScrollEvent*>(event.get());
- scrollEvent->delta += delta;
auto widget = window.find(scrollEvent->x, scrollEvent->y);
if(widget)
{
- scrollEvent->x -= widget->windowX();
- scrollEvent->y -= widget->windowY();
+ scrollEvent->x -= widget->translateToWindowX();
+ scrollEvent->y -= widget->translateToWindowY();
widget->scrollEvent(scrollEvent);
}
@@ -294,6 +226,10 @@ void EventHandler::processEvents()
break;
}
}
+
+ // Probe window and children to readrw as needed.
+ // NOTE: This method will invoke native->redraw() if a redraw is needed.
+ window.updateBuffer();
}
} // GUI::
diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h
index 2a1b657..7e9966c 100644
--- a/plugingui/eventhandler.h
+++ b/plugingui/eventhandler.h
@@ -53,10 +53,6 @@ public:
//! \return A pointer to the event or nullptr if there are none.
std::shared_ptr<Event> getNextEvent();
- //! \brief Get a single event from the event queue without popping it.
- //! \return A pointer to the event or nullptr if there are none.
- std::shared_ptr<Event> peekNextEvent();
-
Notifier<> closeNotifier;
private:
diff --git a/plugingui/knob.cc b/plugingui/knob.cc
index 87779ec..0655a68 100644
--- a/plugingui/knob.cc
+++ b/plugingui/knob.cc
@@ -203,7 +203,7 @@ void Knob::internalSetValue(float value)
currentValue = value;
valueChangedNotifier(currentValue);
- repaintEvent(nullptr);
+ redraw();
}
} // GUI::
diff --git a/plugingui/label.cc b/plugingui/label.cc
index 2ff4f36..781dbca 100644
--- a/plugingui/label.cc
+++ b/plugingui/label.cc
@@ -39,7 +39,7 @@ Label::Label(Widget *parent)
void Label::setText(const std::string& text)
{
_text = text;
- repaintEvent(nullptr);
+ redraw();
}
void Label::setAlignment(TextAlignment alignment)
diff --git a/plugingui/layout.h b/plugingui/layout.h
index bd64fdd..4d20eb6 100644
--- a/plugingui/layout.h
+++ b/plugingui/layout.h
@@ -46,10 +46,10 @@ public:
virtual void resize(std::size_t width, std::size_t height) = 0;
virtual void move(int x, int y) = 0;
- virtual int x() = 0;
- virtual int y() = 0;
- virtual std::size_t width() = 0;
- virtual std::size_t height() = 0;
+ virtual int x() const = 0;
+ virtual int y() const = 0;
+ virtual std::size_t width() const = 0;
+ virtual std::size_t height() const = 0;
private:
Layout* parent;
diff --git a/plugingui/led.cc b/plugingui/led.cc
index 03ea661..f77e31a 100644
--- a/plugingui/led.cc
+++ b/plugingui/led.cc
@@ -41,7 +41,7 @@ void LED::setState(state_t state)
if(this->state != state)
{
this->state = state;
- repaintEvent(nullptr);
+ redraw();
}
}
diff --git a/plugingui/lineedit.cc b/plugingui/lineedit.cc
index c213041..7a8bb53 100644
--- a/plugingui/lineedit.cc
+++ b/plugingui/lineedit.cc
@@ -61,7 +61,7 @@ void LineEdit::setText(const std::string& text)
visibleText = _text;
offsetPos = 0;
- repaintEvent(nullptr);
+ redraw();
textChanged();
}
@@ -94,7 +94,7 @@ void LineEdit::buttonEvent(ButtonEvent *buttonEvent)
break;
}
}
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -189,7 +189,7 @@ void LineEdit::keyEvent(KeyEvent *keyEvent)
break;
}
- repaintEvent(nullptr);
+ redraw();
}
if(change)
diff --git a/plugingui/listboxbasic.cc b/plugingui/listboxbasic.cc
index 730880a..642d03f 100644
--- a/plugingui/listboxbasic.cc
+++ b/plugingui/listboxbasic.cc
@@ -88,7 +88,7 @@ void ListBoxBasic::addItems(const std::vector<ListBoxBasic::Item>& newItems)
int numitems = height() / (font.textHeight() + padding);
scroll.setRange(numitems);
scroll.setMaximum(items.size());
- repaintEvent(nullptr);
+ redraw();
}
void ListBoxBasic::clear()
@@ -97,7 +97,7 @@ void ListBoxBasic::clear()
setSelection(-1);
marked = -1;
scroll.setValue(0);
- repaintEvent(nullptr);
+ redraw();
}
bool ListBoxBasic::selectItem(int index)
@@ -108,7 +108,7 @@ bool ListBoxBasic::selectItem(int index)
}
setSelection(index);
- repaintEvent(nullptr);
+ redraw();
return true;
}
@@ -140,7 +140,7 @@ void ListBoxBasic::clearSelectedValue()
void ListBoxBasic::onScrollBarValueChange(int value)
{
- repaintEvent(nullptr);
+ redraw();
}
void ListBoxBasic::repaintEvent(RepaintEvent* repaintEvent)
@@ -277,7 +277,7 @@ void ListBoxBasic::keyEvent(KeyEvent* keyEvent)
break;
}
- repaintEvent(nullptr);
+ redraw();
}
void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent)
@@ -329,7 +329,7 @@ void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent)
}
}
- repaintEvent(nullptr);
+ redraw();
}
if(buttonEvent->direction != Direction::up)
@@ -346,7 +346,7 @@ void ListBoxBasic::buttonEvent(ButtonEvent* buttonEvent)
}
}
- repaintEvent(nullptr);
+ redraw();
}
if(buttonEvent->doubleClick)
diff --git a/plugingui/mainwindow.cc b/plugingui/mainwindow.cc
index 3a1727f..3b951f5 100644
--- a/plugingui/mainwindow.cc
+++ b/plugingui/mainwindow.cc
@@ -50,13 +50,9 @@ bool MainWindow::processEvents()
// return running;
// }
+ settings_notifier.evaluate();
eventHandler()->processEvents();
- {
- Painter p(*this);
- settings_notifier.evaluate();
- }
-
if(closing)
{
closeNotifier();
diff --git a/plugingui/nativewindow.h b/plugingui/nativewindow.h
index e041994..7b7fd39 100644
--- a/plugingui/nativewindow.h
+++ b/plugingui/nativewindow.h
@@ -69,10 +69,6 @@ public:
//! Sets the window caption in the title bar (if it has one).
virtual void setCaption(const std::string &caption) = 0;
- //! Recreate a window render buffer based on the internal buffer.
- //! This need to be called whenever the internal buffer size has changed.
- virtual void handleBuffer() = 0;
-
//! Draw the internal rendering buffer to the window buffer.
virtual void redraw() = 0;
diff --git a/plugingui/nativewindow_win32.cc b/plugingui/nativewindow_win32.cc
index 23c9012..669ec13 100644
--- a/plugingui/nativewindow_win32.cc
+++ b/plugingui/nativewindow_win32.cc
@@ -379,10 +379,6 @@ void NativeWindowWin32::show()
ShowWindow(m_hwnd, SW_SHOW);
}
-void NativeWindowWin32::handleBuffer()
-{
-}
-
void NativeWindowWin32::hide()
{
ShowWindow(m_hwnd, SW_HIDE);
@@ -390,6 +386,7 @@ void NativeWindowWin32::hide()
void NativeWindowWin32::redraw()
{
+ // Send WM_PAINT message. Buffer transfering is handled in MessageHandler.
if(parent_window == nullptr)
{
RedrawWindow(m_hwnd, nullptr, nullptr, RDW_ERASE|RDW_INVALIDATE);
diff --git a/plugingui/nativewindow_win32.h b/plugingui/nativewindow_win32.h
index b8e1c89..69324e3 100644
--- a/plugingui/nativewindow_win32.h
+++ b/plugingui/nativewindow_win32.h
@@ -52,7 +52,6 @@ public:
void show() override;
void setCaption(const std::string &caption) override;
void hide() override;
- void handleBuffer() override;
void redraw() override;
void grabMouse(bool grab) override;
EventQueue getEvents() override;
diff --git a/plugingui/nativewindow_x11.cc b/plugingui/nativewindow_x11.cc
index bf18ffa..80c0e81 100644
--- a/plugingui/nativewindow_x11.cc
+++ b/plugingui/nativewindow_x11.cc
@@ -223,11 +223,6 @@ void NativeWindowX11::hide()
XUnmapWindow(display, xwindow);
}
-void NativeWindowX11::handleBuffer()
-{
- updateImageFromBuffer();
-}
-
void NativeWindowX11::redraw()
{
if(display == nullptr)
@@ -235,12 +230,7 @@ void NativeWindowX11::redraw()
return;
}
- if(!image)
- {
- window.updateBuffer();
- handleBuffer();
- }
-
+ updateImageFromBuffer();
XShmPutImage(display, xwindow, gc, image, 0, 0, 0, 0,
std::min(image->width, (int)window.width()),
std::min(image->height, (int)window.height()), false);
@@ -286,7 +276,6 @@ void NativeWindowX11::translateXMessage(XEvent& xevent)
//DEBUG(x11, "MotionNotify");
{
auto mouseMoveEvent = std::make_shared<MouseMoveEvent>();
- //mouseMoveEvent->window_id = xevent.xmotion.window;
mouseMoveEvent->x = xevent.xmotion.x;
mouseMoveEvent->y = xevent.xmotion.y;
event_queue.push_back(mouseMoveEvent);
@@ -298,7 +287,6 @@ void NativeWindowX11::translateXMessage(XEvent& xevent)
if(xevent.xexpose.count == 0)
{
auto repaintEvent = std::make_shared<RepaintEvent>();
- //repaintEvent->window_id = xevent.xexpose.window;
repaintEvent->x = xevent.xexpose.x;
repaintEvent->y = xevent.xexpose.y;
repaintEvent->width = xevent.xexpose.width;
@@ -314,17 +302,15 @@ void NativeWindowX11::translateXMessage(XEvent& xevent)
(window.height() != (std::size_t)xevent.xconfigure.height))
{
auto resizeEvent = std::make_shared<ResizeEvent>();
- //resizeEvent->window_id = xevent.xconfigure.window;
resizeEvent->width = xevent.xconfigure.width;
resizeEvent->height = xevent.xconfigure.height;
event_queue.push_back(resizeEvent);
}
- if((window.windowX() != (std::size_t)xevent.xconfigure.x) ||
- (window.windowY() != (std::size_t)xevent.xconfigure.y))
+ if((window.x() != xevent.xconfigure.x) ||
+ (window.y() != xevent.xconfigure.y))
{
auto moveEvent = std::make_shared<MoveEvent>();
- //moveEvent->window_id = xevent.xconfigure.window;
moveEvent->x = xevent.xconfigure.x;
moveEvent->y = xevent.xconfigure.y;
event_queue.push_back(moveEvent);
@@ -340,7 +326,6 @@ void NativeWindowX11::translateXMessage(XEvent& xevent)
{
int scroll = 1;
auto scrollEvent = std::make_shared<ScrollEvent>();
- //scrollEvent->window_id = xevent.xbutton.window;
scrollEvent->x = xevent.xbutton.x;
scrollEvent->y = xevent.xbutton.y;
scrollEvent->delta = scroll * ((xevent.xbutton.button == 4) ? -1 : 1);
@@ -349,7 +334,6 @@ void NativeWindowX11::translateXMessage(XEvent& xevent)
else
{
auto buttonEvent = std::make_shared<ButtonEvent>();
- //buttonEvent->window_id = xevent.xbutton.window;
buttonEvent->x = xevent.xbutton.x;
buttonEvent->y = xevent.xbutton.y;
switch(xevent.xbutton.button) {
@@ -400,7 +384,6 @@ void NativeWindowX11::translateXMessage(XEvent& xevent)
//DEBUG(x11, "KeyPress");
{
auto keyEvent = std::make_shared<KeyEvent>();
- //keyEvent->window_id = xevent.xkey.window;
switch(xevent.xkey.keycode) {
case 113: keyEvent->keycode = Key::left; break;
diff --git a/plugingui/nativewindow_x11.h b/plugingui/nativewindow_x11.h
index a026ac8..f98f151 100644
--- a/plugingui/nativewindow_x11.h
+++ b/plugingui/nativewindow_x11.h
@@ -54,7 +54,6 @@ public:
void show() override;
void hide() override;
void setCaption(const std::string &caption) override;
- void handleBuffer() override;
void redraw() override;
void grabMouse(bool grab) override;
EventQueue getEvents() override;
diff --git a/plugingui/painter.cc b/plugingui/painter.cc
index 3e6fa48..4e7e8ba 100644
--- a/plugingui/painter.cc
+++ b/plugingui/painter.cc
@@ -29,6 +29,12 @@
#include <cmath>
#include <cassert>
+#include "pixelbuffer.h"
+#include "font.h"
+#include "drawable.h"
+#include "image.h"
+#include "canvas.h"
+
namespace GUI
{
@@ -36,14 +42,11 @@ Painter::Painter(Canvas& canvas)
: canvas(canvas)
, pixbuf(canvas.GetPixelBuffer())
{
- canvas.beginPaint();
colour = Colour(0.0f, 0.0f, 0.0f, 0.5f);
}
Painter::~Painter()
{
- canvas.endPaint();
- flush();
}
void Painter::setColour(const Colour& colour)
@@ -161,7 +164,7 @@ void Painter::drawRectangle(int x1, int y1, int x2, int y2)
void Painter::drawFilledRectangle(int x1, int y1, int x2, int y2)
{
- for(int y = y1; y < y2; ++y)
+ for(int y = y1; y <= y2; ++y)
{
drawLine(x1, y, x2, y);
}
@@ -543,12 +546,4 @@ void Painter::drawBar(int x, int y, const Bar& bar, int width, int height)
bar.right->width(), height);
}
-void Painter::flush()
-{
-#ifdef X11
- // Send the "DrawLine" request to the server
- //XFlush(gctx->display);
-#endif/*X11*/
-}
-
} // GUI::
diff --git a/plugingui/painter.h b/plugingui/painter.h
index 7e1fede..3f3c2bb 100644
--- a/plugingui/painter.h
+++ b/plugingui/painter.h
@@ -28,25 +28,23 @@
#include <string>
-#include "widget.h"
#include "colour.h"
-#include "pixelbuffer.h"
-#include "font.h"
-#include "drawable.h"
-#include "texture.h"
-#include "image.h"
namespace GUI
{
+class PixelBufferAlpha;
+class Font;
+class Drawable;
+class Image;
+class Canvas;
+
class Painter
{
public:
Painter(Canvas& canvas);
~Painter();
- void flush();
-
void setColour(const Colour& colour);
void drawLine(int x1, int y1, int x2, int y2);
diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc
index 5d032b4..15270af 100644
--- a/plugingui/pixelbuffer.cc
+++ b/plugingui/pixelbuffer.cc
@@ -156,7 +156,7 @@ void PixelBufferAlpha::pixel(size_t x, size_t y,
unsigned char* red,
unsigned char* green,
unsigned char* blue,
- unsigned char* alpha)
+ unsigned char* alpha) const
{
assert(x < width);
assert(y < height);
diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h
index 762aaa6..b9096c9 100644
--- a/plugingui/pixelbuffer.h
+++ b/plugingui/pixelbuffer.h
@@ -76,7 +76,7 @@ public:
unsigned char* red,
unsigned char* green,
unsigned char* blue,
- unsigned char* alpha);
+ unsigned char* alpha) const;
bool managed{false};
unsigned char* buf{nullptr};
diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc
index 25e735f..c7550c9 100644
--- a/plugingui/progressbar.cc
+++ b/plugingui/progressbar.cc
@@ -43,7 +43,7 @@ void ProgressBar::setState(ProgressBarState state)
if(this->state != state)
{
this->state = state;
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -52,7 +52,7 @@ void ProgressBar::setTotal(std::size_t total)
if(this->total != total)
{
this->total = total;
- repaintEvent(nullptr);
+ redraw();
}
}
@@ -61,7 +61,7 @@ void ProgressBar::setValue(std::size_t value)
if(this->value != value)
{
this->value = value;
- repaintEvent(nullptr);
+ redraw();
}
}
diff --git a/plugingui/scrollbar.cc b/plugingui/scrollbar.cc
index ac5be15..32db4a4 100644
--- a/plugingui/scrollbar.cc
+++ b/plugingui/scrollbar.cc
@@ -41,7 +41,7 @@ void ScrollBar::setRange(int r)
{
rangeValue = r;
setValue(value());
- repaintEvent(nullptr);
+ redraw();
}
int ScrollBar::range()
@@ -57,7 +57,7 @@ void ScrollBar::setMaximum(int m)
rangeValue = maxValue;
}
setValue(value());
- repaintEvent(nullptr);
+ redraw();
}
int ScrollBar::maximum()
@@ -91,7 +91,7 @@ void ScrollBar::setValue(int value)
valueChangeNotifier(value);
- repaintEvent(nullptr);
+ redraw();
}
int ScrollBar::value()
diff --git a/plugingui/slider.cc b/plugingui/slider.cc
index 7405a69..039123e 100644
--- a/plugingui/slider.cc
+++ b/plugingui/slider.cc
@@ -46,7 +46,7 @@ Slider::Slider(Widget *parent)
void Slider::setValue(float newValue)
{
currentValue = newValue;
- repaintEvent(nullptr);
+ redraw();
clickNotifier();
}
@@ -120,7 +120,7 @@ void Slider::buttonEvent(ButtonEvent* buttonEvent)
currentValue = 1;
}
- repaintEvent(nullptr);
+ redraw();
clickNotifier();
}
@@ -139,7 +139,7 @@ void Slider::buttonEvent(ButtonEvent* buttonEvent)
currentValue = 1;
}
- repaintEvent(nullptr);
+ redraw();
clickNotifier();
}
}
@@ -160,7 +160,7 @@ void Slider::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent)
currentValue = 1;
}
- repaintEvent(nullptr);
+ redraw();
clickNotifier();
}
}
diff --git a/plugingui/textedit.cc b/plugingui/textedit.cc
index 6274d37..4e94566 100644
--- a/plugingui/textedit.cc
+++ b/plugingui/textedit.cc
@@ -83,7 +83,7 @@ void TextEdit::setText(const std::string& text)
scroll.setRange(ran);
scroll.setMaximum(preprocessedtext.size());
- repaintEvent(nullptr);
+ redraw();
textChangedNotifier();
}
@@ -190,7 +190,7 @@ void TextEdit::repaintEvent(RepaintEvent* repaintEvent)
void TextEdit::scrolled(int value)
{
(void)value;
- repaintEvent(nullptr);
+ redraw();
}
} // GUI::
diff --git a/plugingui/widget.cc b/plugingui/widget.cc
index 9b8b173..239c233 100644
--- a/plugingui/widget.cc
+++ b/plugingui/widget.cc
@@ -31,7 +31,8 @@
#include "painter.h"
#include "window.h"
-namespace GUI {
+namespace GUI
+{
Widget::Widget(Widget* parent)
: parent(parent)
@@ -67,15 +68,21 @@ void Widget::setVisible(bool visible)
if(visible)
{
- repaintEvent(nullptr);
+ redraw();
}
}
-bool Widget::visible()
+bool Widget::visible() const
{
return _visible;
}
+void Widget::redraw()
+{
+ dirty = true;
+ window()->needsRedraw();
+}
+
void Widget::addChild(Widget* widget)
{
children.push_back(widget);
@@ -124,33 +131,39 @@ void Widget::resize(std::size_t width, std::size_t height)
_width = width;
_height = height;
pixbuf.realloc(width, height);
- repaintEvent(nullptr);
+ redraw();
sizeChangeNotifier(width, height);
}
void Widget::move(int x, int y)
{
+ if((_x == x) &&
+ (_y == y))
+ {
+ return;
+ }
+
_x = x;
_y = y;
positionChangeNotifier(x, y);
}
-int Widget::x()
+int Widget::x() const
{
return _x;
}
-int Widget::y()
+int Widget::y() const
{
return _y;
}
-std::size_t Widget::width()
+std::size_t Widget::width() const
{
return _width;
}
-std::size_t Widget::height()
+std::size_t Widget::height() const
{
return _height;
}
@@ -160,44 +173,6 @@ PixelBufferAlpha& Widget::GetPixelBuffer()
return pixbuf;
}
-void Widget::beginPaint()
-{
- if(_window)
- {
- _window->beginPaint();
- }
-}
-
-void Widget::endPaint()
-{
- if(_window)
- {
- _window->endPaint();
- }
-}
-
-size_t Widget::windowX()
-{
- size_t window_x = x();
- if(parent)
- {
- window_x += parent->windowX();
- }
-
- return window_x;
-}
-
-size_t Widget::windowY()
-{
- size_t window_y = y();
- if(parent)
- {
- window_y += parent->windowY();
- }
-
- return window_y;
-}
-
ImageCache& Widget::getImageCache()
{
assert(parent);
@@ -231,8 +206,14 @@ std::vector<PixelBufferAlpha*> Widget::getPixelBuffers()
{
std::vector<PixelBufferAlpha*> pixelBuffers;
- pixbuf.x = windowX();
- pixbuf.y = windowY();
+ pixbuf.x = translateToWindowX();
+ pixbuf.y = translateToWindowY();
+
+ if(dirty)
+ {
+ repaintEvent(nullptr);
+ dirty = false;
+ }
pixelBuffers.push_back(&pixbuf);
@@ -254,16 +235,26 @@ bool Widget::hasKeyboardFocus()
return window()->keyboardFocus() == this;
}
-void Widget::repaintChildren(RepaintEvent* repaintEvent)
+std::size_t Widget::translateToWindowX()
{
- Painter p(*this); // make sure pixbuf refcount is incremented.
+ size_t window_x = x();
+ if(parent)
+ {
+ window_x += parent->translateToWindowX();
+ }
- this->repaintEvent(repaintEvent);
+ return window_x;
+}
- for(auto child : children)
+std::size_t Widget::translateToWindowY()
+{
+ size_t window_y = y();
+ if(parent)
{
- child->repaintChildren(repaintEvent);
+ window_y += parent->translateToWindowY();
}
+
+ return window_y;
}
} // GUI::
diff --git a/plugingui/widget.h b/plugingui/widget.h
index 4ea79e9..0485c32 100644
--- a/plugingui/widget.h
+++ b/plugingui/widget.h
@@ -52,25 +52,22 @@ public:
virtual void show();
virtual void hide();
+ void setVisible(bool visible);
+ bool visible() const;
+
+ //! Mark widget dirty and shedule redraw on next window redraw.
+ void redraw();
// From LayoutItem
virtual void resize(std::size_t width, std::size_t height) override;
virtual void move(int x, int y) override;
- virtual int x() override;
- virtual int y() override;
- virtual std::size_t width() override;
- virtual std::size_t height() override;
+ virtual int x() const override;
+ virtual int y() const override;
+ virtual std::size_t width() const override;
+ virtual std::size_t height() const override;
// From Canvas
PixelBufferAlpha& GetPixelBuffer() override;
- void beginPaint() override;
- void endPaint() override;
-
- //! Translate x-coordinate from parent-space to window-space.
- virtual size_t windowX();
-
- //! Translate y-coordinate from parent-space to window-space.
- virtual size_t windowY();
virtual bool isFocusable() { return false; }
virtual bool catchMouse() { return false; }
@@ -97,14 +94,17 @@ public:
bool hasKeyboardFocus();
- bool visible();
- void setVisible(bool visible);
-
Notifier<std::size_t, std::size_t> sizeChangeNotifier; // (width, height)
Notifier<int, int> positionChangeNotifier; // (x, y)
protected:
- void repaintChildren(RepaintEvent* repaintEvent);
+ friend class EventHandler;
+
+ //! Translate x-coordinate from parent-space to window-space.
+ virtual std::size_t translateToWindowX();
+
+ //! Translate y-coordinate from parent-space to window-space.
+ virtual std::size_t translateToWindowY();
PixelBufferAlpha pixbuf{0,0};
@@ -119,6 +119,8 @@ protected:
std::size_t _height{0};
bool _visible{true};
+
+ bool dirty{true};
};
} // GUI::
diff --git a/plugingui/window.cc b/plugingui/window.cc
index 98c0c80..44c8e12 100644
--- a/plugingui/window.cc
+++ b/plugingui/window.cc
@@ -42,7 +42,8 @@
#include "nativewindow_pugl.h"
#endif
-namespace GUI {
+namespace GUI
+{
Window::Window(void* native_window)
: Widget(nullptr)
@@ -101,40 +102,10 @@ void Window::move(int x, int y)
native->move(x, y);
}
-int Window::x()
-{
- return native->getPosition().first;
-}
-
-int Window::y()
-{
- return native->getPosition().second;
-}
-
-size_t Window::width()
-{
- return native->getSize().first;
-}
-
-size_t Window::height()
-{
- return native->getSize().second;
-}
-
-size_t Window::windowX()
-{
- return 0;
-}
-
-size_t Window::windowY()
-{
- return 0;
-}
-
void Window::show()
{
Widget::show();
- repaintChildren(nullptr);
+ redraw();
native->show();
}
@@ -171,12 +142,12 @@ void Window::setKeyboardFocus(Widget* widget)
if(oldFocusWidget)
{
- oldFocusWidget->repaintEvent(nullptr);
+ oldFocusWidget->redraw();
}
if(_keyboardFocus)
{
- _keyboardFocus->repaintEvent(nullptr);
+ _keyboardFocus->redraw();
}
}
@@ -202,18 +173,34 @@ void Window::setMouseFocus(Widget* widget)
}
-void Window::redraw()
+void Window::needsRedraw()
{
- native->redraw();
+ needs_redraw = true;
+}
+
+std::size_t Window::translateToWindowX()
+{
+ return 0;
+}
+
+std::size_t Window::translateToWindowY()
+{
+ return 0;
}
//! Called by event handler when an windowmanager/OS window resize event has
//! been received. Do not call this directly.
void Window::resized(std::size_t width, std::size_t height)
{
- wpixbuf.realloc(this->width(), this->height());
- Widget::resize(this->width(), this->height());
- updateBuffer();
+ auto size = native->getSize();
+ if((wpixbuf.width == size.first) &&
+ (wpixbuf.height == size.second))
+ {
+ return;
+ }
+ wpixbuf.realloc(size.first, size.second);
+ Widget::resize(size.first, size.second);
+ //updateBuffer();
}
//! Called by event handler when an windowmanager/OS window move event has
@@ -224,9 +211,20 @@ void Window::moved(int x, int y)
Widget::move(x, y);
}
-void Window::updateBuffer()
+bool Window::updateBuffer()
{
- for(auto pixelBuffer : getPixelBuffers())
+ if(!native)
+ {
+ return false;
+ }
+
+ if(!needs_redraw)
+ {
+ // Nothing changed, don't update anything.
+ return false;
+ }
+
+ for(const auto& pixelBuffer : getPixelBuffers())
{
size_t updateWidth = pixelBuffer->width;
size_t updateHeight = pixelBuffer->height;
@@ -258,35 +256,10 @@ void Window::updateBuffer()
}
}
- native->handleBuffer();
-}
-
-void Window::beginPaint()
-{
- ++refcount;
- if(refcount > maxRefcount)
- {
- maxRefcount = refcount;
- }
-}
-
-void Window::endPaint()
-{
- if(refcount)
- {
- --refcount;
- }
+ native->redraw();
+ needs_redraw = false;
- if(!refcount)
- {
- // Did we go deep enough for a buffer update?
- if(maxRefcount > 1)
- {
- updateBuffer();
- redraw();
- }
- maxRefcount = 0;
- }
+ return true;
}
} // GUI::
diff --git a/plugingui/window.h b/plugingui/window.h
index 0a10b3e..cfb004d 100644
--- a/plugingui/window.h
+++ b/plugingui/window.h
@@ -50,12 +50,6 @@ public:
// From Widget:
void resize(std::size_t width, std::size_t height) override;
void move(int x, int y) override;
- int x() override;
- int y() override;
- size_t width() override;
- size_t height() override;
- size_t windowX() override;
- size_t windowY() override;
void show() override;
void hide() override;
Window* window() override;
@@ -73,18 +67,25 @@ public:
Widget* mouseFocus();
void setMouseFocus(Widget* widget);
+ //! Tag the window buffer dirty to be rendered.
+ void needsRedraw();
+
protected:
// For the EventHandler
friend class EventHandler;
- void redraw();
+
+ // From Widget:
+ std::size_t translateToWindowX() override;
+ std::size_t translateToWindowY() override;
void resized(std::size_t width, std::size_t height);
void moved(int x, int y);
- void updateBuffer();
+
+ //! Returns true if window pixel buffer changed and needs to be copied to
+ //! native window.
+ bool updateBuffer();
// For the Painter
friend class Widget;
- void beginPaint() override;
- void endPaint() override;
// For the NativeWindow
friend class NativeWindowX11;
@@ -103,6 +104,7 @@ protected:
size_t maxRefcount{0};
+ bool needs_redraw{false};
ImageCache image_cache;
};