Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
.
[graphlib.git] / DrawingWindow.cpp
index c68b7b8..284aaea 100644 (file)
@@ -1,7 +1,6 @@
 #include "DrawingWindow.h"
 #include <QApplication>
 #include <QPaintEvent>
-#include <QPainter>
 #include <QThread>
 #include <QTimerEvent>
 
@@ -21,6 +20,39 @@ private:
     friend class DrawingWindow;
 };
 
+enum UserEvents {
+    SyncRequest = QEvent::User,
+    CloseRequest,
+    DrawTextRequest,
+};
+
+namespace {
+    class SyncRequestEvent: public QEvent {
+    public:
+        SyncRequestEvent(): QEvent(static_cast<QEvent::Type>(SyncRequest))
+        { }
+    };
+
+    class CloseRequestEvent: public QEvent {
+    public:
+        CloseRequestEvent(): QEvent(static_cast<QEvent::Type>(CloseRequest))
+        { }
+    };
+
+    class DrawTextEvent: public QEvent {
+    public:
+        const int x;
+        const int y;
+        const char *text;
+        const int flags;
+        DrawTextEvent(int x_, int y_, const char* text_, int flags_)
+            : QEvent(static_cast<QEvent::Type>(DrawTextRequest))
+            , x(x_), y(y_), text(text_), flags(flags_)
+        { }
+    };
+
+}
+
 //--- DrawingWindow ----------------------------------------------------
 
 DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h)
@@ -56,32 +88,40 @@ DrawingWindow::~DrawingWindow()
     delete image;
 }
 
-void DrawingWindow::setColor(float red, float green, float blue)
+void DrawingWindow::setColor(unsigned int color)
 {
-    fgColor.setRgbF(red, green, blue);
-    applyColor();
+    setColor(QColor::fromRgb(color));
 }
 
 void DrawingWindow::setColor(const char *name)
 {
-    fgColor.setNamedColor(name);
-    applyColor();
+    setColor(QColor(name));
 }
 
-void DrawingWindow::setBgColor(float red, float green, float blue)
+void DrawingWindow::setColor(float red, float green, float blue)
 {
-    bgColor.setRgbF(red, green, blue);
+    setColor(QColor::fromRgbF(red, green, blue));
+}
+
+void DrawingWindow::setBgColor(unsigned int color)
+{
+    setBgColor(QColor::fromRgb(color));
 }
 
 void DrawingWindow::setBgColor(const char *name)
 {
-    bgColor.setNamedColor(name);
+    setBgColor(QColor(name));
+}
+
+void DrawingWindow::setBgColor(float red, float green, float blue)
+{
+    setBgColor(QColor::fromRgbF(red, green, blue));
 }
 
 void DrawingWindow::clearGraph()
 {
     safeLock(imageMutex);
-    painter->fillRect(image->rect(), bgColor);    
+    painter->fillRect(image->rect(), getBgColor());
     dirty();
     safeUnlock(imageMutex);
 }
@@ -116,7 +156,7 @@ void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
 
 void DrawingWindow::fillRect(int x1, int y1, int x2, int y2)
 {
-    painter->setBrush(fgColor);
+    painter->setBrush(getColor());
     drawRect(x1, y1, x2, y2);
     painter->setBrush(Qt::NoBrush);
 }
@@ -134,19 +174,31 @@ void DrawingWindow::drawCircle(int x, int y, int r)
 
 void DrawingWindow::fillCircle(int x, int y, int r)
 {
-    painter->setBrush(fgColor);
+    painter->setBrush(getColor());
     drawCircle(x, y, r);
     painter->setBrush(Qt::NoBrush);
 }
 
-void DrawingWindow::drawText(int x, int y, const char *text)
+void DrawingWindow::drawText(int x, int y, const char *text, int flags)
 {
-    QRect r(image->rect());
-    r.moveTo(x, y);
-    safeLock(imageMutex);
-    painter->drawText(r, 0, text, &r);
-    dirty(r);
-    safeUnlock(imageMutex);
+    safeLock(syncMutex);
+    if (!terminateThread) {
+        qApp->postEvent(this, new DrawTextEvent(x, y, text, flags));
+        syncCondition.wait(&syncMutex);
+    }
+    safeUnlock(syncMutex);
+}
+
+void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags)
+{
+    painter->setBackgroundMode(Qt::OpaqueMode);
+    drawText(x, y, text, flags);
+    painter->setBackgroundMode(Qt::TransparentMode);
+}
+
+unsigned int DrawingWindow::getPointColor(int x, int y)
+{
+    return image->pixel(x, y);
 }
 
 bool DrawingWindow::sync(unsigned long time)
@@ -156,7 +208,7 @@ bool DrawingWindow::sync(unsigned long time)
     if (terminateThread) {
         synced = false;
     } else {
-        qApp->postEvent(this, new QEvent(QEvent::User));
+        qApp->postEvent(this, new SyncRequestEvent());
         synced = syncCondition.wait(&syncMutex, time);
     }
     safeUnlock(syncMutex);
@@ -165,7 +217,7 @@ bool DrawingWindow::sync(unsigned long time)
 
 void DrawingWindow::closeGraph()
 {
-    qApp->postEvent(this, new QEvent(QEvent::Type(QEvent::User + 1)));
+    qApp->postEvent(this, new CloseRequestEvent());
 }
 
 void DrawingWindow::sleep(unsigned long secs)
@@ -203,24 +255,16 @@ void DrawingWindow::closeEvent(QCloseEvent *ev)
 void DrawingWindow::customEvent(QEvent *ev)
 {
     switch ((int )ev->type()) {
-    case QEvent::User:
-        mayUpdate();
-        qApp->sendPostedEvents(this, QEvent::UpdateLater);
-        qApp->sendPostedEvents(this, QEvent::UpdateRequest);
-        qApp->sendPostedEvents(this, QEvent::Paint);
-        qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
-                            QEventLoop::ExcludeSocketNotifiers |
-                            QEventLoop::DeferredDeletion |
-                            QEventLoop::X11ExcludeTimers);
-        qApp->flush();
-        qApp->syncX();
-        syncMutex.lock();
-        syncCondition.wakeAll();
-        syncMutex.unlock();
+    case SyncRequest:
+        realSync();
         break;
-    case QEvent::User + 1:
+    case CloseRequest:
         close();
         break;
+    case DrawTextRequest:
+        DrawTextEvent* tev = dynamic_cast<DrawTextEvent *>(ev);
+        realDrawText(tev->x, tev->y, tev->text, tev->flags);
+        break;
     }
 }
 
@@ -251,9 +295,11 @@ void DrawingWindow::paintEvent(QPaintEvent *ev)
 
 void DrawingWindow::showEvent(QShowEvent *ev)
 {
+    QWidget::showEvent(ev);
+    qApp->flush();
+    qApp->syncX();
     timer.start(paintInterval, this);
     thread->start_once(QThread::IdlePriority);
-    QWidget::showEvent(ev);
 }
 
 void DrawingWindow::timerEvent(QTimerEvent *ev)
@@ -289,13 +335,31 @@ void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
 }
 
 inline
-void DrawingWindow::applyColor()
+void DrawingWindow::setColor(const QColor& color)
 {
     QPen pen(painter->pen());
-    pen.setColor(fgColor);
+    pen.setColor(color);
     painter->setPen(pen);
 }
 
+inline
+void DrawingWindow::setBgColor(const QColor& color)
+{
+    painter->setBackground(color);
+}
+
+inline
+QColor DrawingWindow::getColor()
+{
+    return painter->pen().color();
+}
+
+inline
+QColor DrawingWindow::getBgColor()
+{
+    return painter->background().color();
+}
+
 inline
 void DrawingWindow::safeLock(QMutex &mutex)
 {
@@ -354,6 +418,59 @@ void DrawingWindow::mayUpdate()
         update(rect);
 }
 
+void DrawingWindow::realSync()
+{
+    mayUpdate();
+    qApp->sendPostedEvents(this, QEvent::UpdateLater);
+    qApp->sendPostedEvents(this, QEvent::UpdateRequest);
+    qApp->sendPostedEvents(this, QEvent::Paint);
+    qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
+                        QEventLoop::ExcludeSocketNotifiers |
+                        QEventLoop::DeferredDeletion |
+                        QEventLoop::X11ExcludeTimers);
+    qApp->flush();
+    qApp->syncX();
+    syncMutex.lock();
+    syncCondition.wakeAll();
+    syncMutex.unlock();
+}
+
+void DrawingWindow::realDrawText(int x, int y, const char *text, int flags)
+{
+    QRect r(image->rect());
+    switch (flags & Qt::AlignHorizontal_Mask) {
+    case Qt::AlignRight:
+        r.setRight(x);
+        break;
+    case Qt::AlignHCenter:
+        if (x < width / 2)
+            r.setLeft(2 * x - width + 1);
+        else
+            r.setRight(2 * x);
+        break;
+    default:
+        r.setLeft(x);
+    }
+    switch (flags & Qt::AlignVertical_Mask) {
+    case Qt::AlignBottom:
+        r.setBottom(y);
+        break;
+    case Qt::AlignVCenter:
+        if (y < height / 2)
+            r.setTop(2 * y - height + 1);
+        else
+            r.setBottom(2 * y);
+        break;
+    default:
+        r.setTop(y);
+    }
+    syncMutex.lock();
+    painter->drawText(r, flags, text, &r);
+    dirty(r);
+    syncCondition.wakeAll();
+    syncMutex.unlock();
+}
+
 //--- DrawingThread ----------------------------------------------------
 
 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)