Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
simplified
[graphlib.git] / DrawingWindow.cpp
index 04033ca..9a8d501 100644 (file)
 #include "DrawingWindow.h"
-#include <QPainter>
 #include <QPaintEvent>
+#include <QThread>
+#include <QTimerEvent>
 
-#include <iostream>
+class DrawingWindow::DrawingThread: public QThread {
+public:
+    DrawingThread(DrawingWindow &w, ThreadFunction f)
+        : drawingWindow(w)
+        , threadFunction(f)
+    {
+    }
+
+    void run()
+    {
+        exit(threadFunction(drawingWindow));
+    }
 
-DrawingWindow::DrawingWindow(DrawingArea &a)
+private:
+    DrawingWindow &drawingWindow;
+    ThreadFunction threadFunction;
+
+};
+
+DrawingWindow::DrawingWindow(ThreadFunction fun, int width, int height)
     : QWidget()
-    , drawingArea(a)
-    , pixmap(a.size())
 {
-    initialize();
+    initialize(fun, width, height);
 }
 
-DrawingWindow::DrawingWindow(QWidget *parent, DrawingArea &a)
+DrawingWindow::DrawingWindow(QWidget *parent,
+                             ThreadFunction fun, int width, int height)
     : QWidget(parent)
-    , drawingArea(a)
-    , pixmap(a.size())
 {
-    initialize();
+    initialize(fun, width, height);
 }
 
 DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
-                             DrawingArea &a)
+                             ThreadFunction fun, int width, int height)
     : QWidget(parent, flags)
-    , drawingArea(a)
-    , pixmap(a.size())
 {
-    initialize();
+    initialize(fun, width, height);
+}
+
+void DrawingWindow::initialize(ThreadFunction fun, int width, int height)
+{
+    image = new QImage(width, height, QImage::Format_RGB32);
+    image->fill(QColor(Qt::white).rgb());
+
+    painter = new QPainter(image);
+
+#ifdef USE_PIXMAP_CACHE
+    pixmap = new QPixmap(image->size());
+    QPainter pixmapPainter(pixmap);
+    pixmapPainter.drawImage(0, 0, *image);
+#endif
+
+    dirtyFlag = false;
+
+    setFocusPolicy(Qt::StrongFocus);
+    setFixedSize(image->size());
+    setAttribute(Qt::WA_OpaquePaintEvent);
+    setFocus();
+    timer.start(paintInterval, this);
+
+    thread = new DrawingThread(*this, fun);
+    thread_started = false;
+}
+
+DrawingWindow::~DrawingWindow()
+{
+    delete thread;
+#ifdef USE_PIXMAP_CACHE
+    delete pixmap;
+#endif
+    delete painter;
+    delete image;
+}
+
+void DrawingWindow::setColor(const QColor &color)
+{
+    QPen pen(painter->pen());
+    pen.setColor(color);
+    painter->setPen(pen);
+}
+
+void DrawingWindow::setColor(float red, float green, float blue)
+{
+    QColor color;
+    color.setRgbF(red, green, blue);
+    this->setColor(color);
+}
+
+void DrawingWindow::drawPoint(int x, int y)
+{
+    lock();
+    painter->drawPoint(x, y);
+    setDirtyRect(x, y);
+    unlock();
+}
+
+void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
+{
+    lock();
+    painter->drawLine(x1, y1, x2, y2);
+    setDirtyRect(x1, y1, x2, y2);
+    unlock();
 }
 
 void DrawingWindow::paintEvent(QPaintEvent *ev)
 {
+    QPainter widgetPainter(this);
     QRect rect = ev->rect();
-    drawingArea.lock();
-    if (drawingArea.isDirty()) {
-        QPainter pixmapPainter(&pixmap);
-        pixmapPainter.drawImage(drawingArea.getDirtyRect(),
-                                drawingArea.getImage(),
-                                drawingArea.getDirtyRect());
-        drawingArea.setClean();
-        rect |= drawingArea.getDirtyRect();
+#ifdef USE_PIXMAP_CACHE
+    widgetPainter.drawPixmap(rect, *pixmap, rect);
+#else
+    lock();
+    widgetPainter.drawImage(rect, *image, rect);
+    unlock();
+#endif
+}
+
+void DrawingWindow::showEvent(QShowEvent *ev)
+{
+    if (!thread_started) {
+        thread->start();
+        thread_started = true;
     }
-    drawingArea.unlock();
-    QPainter painter(this);
-    painter.drawPixmap(0, 0, pixmap);
+    QWidget::showEvent(ev);
 }
 
 void DrawingWindow::timerEvent(QTimerEvent *ev)
 {
     if (ev->timerId() == timer.timerId()) {
-        update();
+        lock();
+        if (dirtyFlag) {
+#ifdef USE_PIXMAP_CACHE
+            QPainter pixmapPainter(pixmap);
+            pixmapPainter.drawImage(dirtyRect, *image, dirtyRect);
+#endif
+            dirtyFlag = false;
+            update(dirtyRect);
+            timer.start(paintInterval, this);
+        }
+        unlock();
     } else {
         QWidget::timerEvent(ev);
     }
 }
 
-void DrawingWindow::initialize()
+void DrawingWindow::setDirtyRect()
 {
-    setFocusPolicy(Qt::StrongFocus);
-    setFixedSize(drawingArea.getImage().size());
-    setAttribute(Qt::WA_OpaquePaintEvent);
-    timer.start(50, this);
+    setDirtyRect(QRect(0, 0, width(), height()));
+}
+
+void DrawingWindow::setDirtyRect(int x, int y)
+{
+    setDirtyRect(QRect(x, y, 1, 1));
+}
+
+void DrawingWindow::setDirtyRect(int x1, int y1, int x2, int y2)
+{
+    QRect r;
+    r.setCoords(x1, y1, x2, y2);
+    setDirtyRect(r.normalized());
+}
+
+void DrawingWindow::setDirtyRect(const QRect &rect)
+{
+    if (dirtyFlag) {
+        dirtyRect |= rect;
+    } else {
+        dirtyFlag = true;
+        dirtyRect = rect;
+    }
 }