Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
.
[graphlib.git] / DrawingWindow.cpp
index 6a4f56e..0cd3633 100644 (file)
+/*
+ * Copyright (c) 2007, Arnaud Giersch <arnaud.giersch@iut-bm.univ-fcomte.fr>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #include "DrawingWindow.h"
 #include <QApplication>
 #include <QPaintEvent>
 #include <QThread>
 #include <QTimerEvent>
 
-/*! Classe de thread.
+/*! \class DrawingWindow
+ *  \brief Fenêtre de dessin.
+ *
+ * \author Arnaud Giersch <arnaud.giersch@iut-bm.univ-fcomte.fr>
+ * \date novembre 2007
+ *
+ * Cette classe décrit un widget Qt permettant d'écrire des
+ * applications graphiques simples.  Pour cela, il faut définir une
+ * fonction de dessin.  Cette fonction ne retourne rien et prend comme
+ * unique paramètre une référence vers un objet de class
+ * DrawingWindow.
+ *
+ * La fonction devra ensuite être passée en paramètre pour les
+ * constructeurs de la classe, ainsi que les dimension requises pour
+ * la fenêtre graphique.  Le programme est ensuite compilé comme
+ * n'importe quel programme Qt.
+ *
+ * Concrètement, la fonction sera exécutée dans un nouveau thread,
+ * tandis que le thread principal s'occupera de la gestion des
+ * évènements et du rendu dans la fenêtre.
+ *
+ * <b>NB.</b> Pour toutes les méthodes de dessin, le coin en haut à gauche
+ * de la fenêtre a les coordonnées (0, 0).  Le coin en bas à droite de
+ * la fenêtre a les coordonnées (largeur - 1, hauteur - 1), si la
+ * fenêtre est de dimension largeur × hauteur.
+ *
+ * Un appui sur la touche <Esc> provoque la fermeture de la fenêtre.
+ * Comme pour la plupart des applications, il est également possible
+ * de fermer la fenêtre via le gestionnaire de fenêtres.
+ *
+ * Il est possible, dans une application, d'ouvrir plusieurs fenêtres,
+ * avec des fonctions de dessin éventuellement différentes.
+ * L'application se terminera normalement lorsque la dernière fenêtre
+ * sera fermée.
+ */
+
+/*! \example hello.cpp
+ *
+ * Voir le code source à la fin de la page.  Pour compiler et exécuter
+ * ce programme, il faut :
+ *
+ * <b>1. Créer le fichier \c hello.pro</b>
+ *
+ * Pour simplifier, ce fichier contient la liste des fichiers sources
+ * composant le programme.
+ *
+ * \include hello.pro
+ *
+ * <b>2. Créer le fichier \c Makefile avec la commande :</b>
+ *
+ * \verbatim qmake-qt4 hello.pro \endverbatim
+ * ou tout simplement :
+ * \verbatim qmake-qt4 \endverbatim
+ *
+ * <b>3. Compiler le programme avec la commande :</b>
+ *
+ * \verbatim make hello \endverbatim
+ * ou tout simplement :
+ * \verbatim make \endverbatim
+ *
+ * <b>4. Exécuter le programme avec la commande :</b>
+ *
+ * \verbatim ./exemple \endverbatim
+ *
+ * <b>Code source de l'exemple</b>
  */
+
+/*! \example exemple.cpp
+ *
+ * Un exemple un peu plus sophistiqué.
+ */
+
+//! Classe de thread.
 class DrawingThread: public QThread {
 public:
     DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f);
@@ -28,24 +128,21 @@ enum UserEvents {
     DrawTextRequest,            //!< Demande d'écriture de texte.
 };
 
-/*! Demande de synchronisation.
- */
+//! Demande de synchronisation.
 class SyncRequestEvent: public QEvent {
 public:
     SyncRequestEvent(): QEvent(static_cast<QEvent::Type>(SyncRequest))
     { }
 };
 
-/*! Demande de fermeture de fenêtre.
- */
+//! Demande de fermeture de fenêtre.
 class CloseRequestEvent: public QEvent {
 public:
     CloseRequestEvent(): QEvent(static_cast<QEvent::Type>(CloseRequest))
     { }
 };
 
-/*! Demande de tracé de texte. 
- */
+//! Demande de tracé de texte. 
 class DrawTextEvent: public QEvent {
 public:
     const int x;
@@ -60,8 +157,31 @@ public:
 
 //--- DrawingWindow ----------------------------------------------------
 
-/*! Constructeur.
- *
+/*! \file DrawingWindow.h
+ *  \brief Classe DrawingWindow.
+ */
+
+/*! \typedef DrawingWindow::ThreadFunction
+ *  \brief Type de la fonction de dessin, passée en paramètre de construction.
+ */
+/*! \var DrawingWindow::DEFAULT_WIDTH
+ *  \brief Largeur par défaut de la fenêtre.
+ */
+/*! \var DrawingWindow::DEFAULT_HEIGHT
+ *  \brief Hauteur par défaut de la fenêtre.
+ */
+/*! \var DrawingWindow::width
+ *  \brief Largeur de la fenêtre.
+ */
+/*! \var DrawingWindow::height
+ *  \brief Hauteur de la fenêtre.
+ */
+/*! \var DrawingWindow::paintInterval
+ *  \brief Intervalle de temps entre deux rendus (ms).
+ */
+
+//! Constructeur.
+/*!
  * Construit une nouvelle fenêtre de dessin avec les dimensions
  * passées en paramètres.  La fonction fun sera exécutée dans un
  * nouveau thread.
@@ -80,8 +200,8 @@ DrawingWindow::DrawingWindow(ThreadFunction fun, int width_, int height_)
     initialize(fun);
 }
 
-/*! Constructeur.
- *
+//! Constructeur.
+/*!
  * Construit un nouveau widget de dessin avec les dimensions passées
  * en paramètres.  La fonction fun sera exécutée dans un nouveau
  * thread.
@@ -102,8 +222,8 @@ DrawingWindow::DrawingWindow(QWidget *parent,
     initialize(fun);
 }
 
-/*! Constructeur.
- *
+//! Constructeur.
+/*!
  * Construit un nouveau widget de dessin avec les dimensions passées
  * en paramètres.  La fonction fun sera exécutée dans un nouveau
  * thread.
@@ -125,8 +245,7 @@ DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
     initialize(fun);
 }
 
-/*! Destructeur.
- */
+//! Destructeur.
 DrawingWindow::~DrawingWindow()
 {
     delete thread;
@@ -134,8 +253,8 @@ DrawingWindow::~DrawingWindow()
     delete image;
 }
 
-/*! Change la couleur de dessin.
- *
+//! Change la couleur de dessin.
+/*!
  * La couleur est un entier, tel que retourné par getPointColor.
  * Normalement de la forme #00RRGGBB.
  *
@@ -150,8 +269,8 @@ void DrawingWindow::setColor(unsigned int color)
     setColor(QColor::fromRgb(color));
 }
 
-/*! Change la couleur de dessin.
- *
+//! Change la couleur de dessin.
+/*!
  * Le nom de couleur est de la forme "black", "white", "red", "blue", ...
  *
  * \param name          nom de couleur
@@ -165,8 +284,8 @@ void DrawingWindow::setColor(const char *name)
     setColor(QColor(name));
 }
 
-/*! Change la couleur de dessin.
- *
+//! Change la couleur de dessin.
+/*!
  * Les composantes de rouge, vert et bleu de la couleur doivent être
  * compris entre 0 et 1.  Si le trois composantes sont à 0, on obtient
  * du noir; si les trois composantes sont à 1, on obtient du blanc.
@@ -183,8 +302,8 @@ void DrawingWindow::setColor(float red, float green, float blue)
     setColor(QColor::fromRgbF(red, green, blue));
 }
 
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
  * \param color         couleur
  *
  * \see setBgColor(const char *), setBgColor(float, float, float),
@@ -197,8 +316,8 @@ void DrawingWindow::setBgColor(unsigned int color)
     setBgColor(QColor::fromRgb(color));
 }
 
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
  * \param name          nom de couleur
  *
  * \see setBgColor(unsigned int), setBgColor(float, float, float),
@@ -211,8 +330,8 @@ void DrawingWindow::setBgColor(const char *name)
     setBgColor(QColor(name));
 }
 
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
  * \param red           composante de rouge
  * \param green         composante de vert
  * \param blue          composante de bleu
@@ -226,8 +345,8 @@ void DrawingWindow::setBgColor(float red, float green, float blue)
     setBgColor(QColor::fromRgbF(red, green, blue));
 }
 
-/*! Efface la fenêtre.
- *
+//! Efface la fenêtre.
+/*!
  * La fenêtre est effacée avec la couleur de fond courante.
  *
  * \see setBgColor
@@ -240,8 +359,8 @@ void DrawingWindow::clearGraph()
     safeUnlock(imageMutex);
 }
 
-/*! Dessine un point.
- *
+//! Dessine un point.
+/*!
  * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
  * dessin courante.
  *
@@ -257,8 +376,8 @@ void DrawingWindow::drawPoint(int x, int y)
     safeUnlock(imageMutex);
 }
 
-/*! Dessine un segment.
- *
+//! Dessine un segment.
+/*!
  * Dessine un segement de droite entre les coordonnées (x1, y1) et
  * (x2, y2), avec la couleur de dessin courante.
  *
@@ -275,8 +394,8 @@ void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
     safeUnlock(imageMutex);
 }
 
-/*! Dessine un rectangle.
- *
+//! Dessine un rectangle.
+/*!
  * Dessine le rectangle parallèle aux axes et défini par les
  * coordonnées de deux sommets opposés (x1, y1) et (x2, y2).  Utilise
  * la couleur de dessin courante.
@@ -298,8 +417,8 @@ void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
     safeUnlock(imageMutex);
 }
 
-/*! Dessine un rectangle plein.
- *
+//! Dessine un rectangle plein.
+/*!
  * Dessine le rectangle plein parallèle aux axes et défini par les
  * coordonnées de deux sommets opposés (x1, y1) et (x2, y2).  Utilise
  * la couleur de dessin courante.
@@ -316,8 +435,8 @@ void DrawingWindow::fillRect(int x1, int y1, int x2, int y2)
     painter->setBrush(Qt::NoBrush);
 }
 
-/*! Dessine un cercle.
- *
+//! Dessine un cercle.
+/*!
  * Dessine un cercle de centre (x, y) et de rayon r.  Utilise la
  * couleur de dessin courante.
  *
@@ -337,8 +456,8 @@ void DrawingWindow::drawCircle(int x, int y, int r)
     safeUnlock(imageMutex);
 }
 
-/*! Dessine un disque.
- *
+//! Dessine un disque.
+/*!
  * Dessine un disque (cercle plein) de centre (x, y) et de rayon r.
  * Utilise la couleur de dessin courante.
  *
@@ -354,8 +473,8 @@ void DrawingWindow::fillCircle(int x, int y, int r)
     painter->setBrush(Qt::NoBrush);
 }
 
-/*! Écrit du texte.
- *
+//! Écrit du texte.
+/*!
  * Écrit le texte text, aux coordonnées (x, y) et avec les paramètres
  * d'alignement flags.  Le texte est écrit avec la couleur de dessin
  * courante.  Les flags sont une combinaison (ou binaire) de
@@ -380,8 +499,8 @@ void DrawingWindow::drawText(int x, int y, const char *text, int flags)
     safeUnlock(syncMutex);
 }
 
-/*! Écrit du texte sur fond coloré.
- *
+//! Écrit du texte sur fond coloré.
+/*!
  * Écrit du texte comme drawText, mais l'arrière-plan est coloré avec
  * la couleur de fond courante.
  *
@@ -399,8 +518,8 @@ void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags)
 }
 
 
-/*! Retourne la couleur d'un pixel.
- *
+//! Retourne la couleur d'un pixel.
+/*!
  * Retourne la couleur du pixel de coordonnées (x, y).  La valeur
  * retournée peut servir de paramètres à setColor(unsigned int) ou
  * setBgColor(unsigned int).
@@ -415,8 +534,8 @@ unsigned int DrawingWindow::getPointColor(int x, int y)
     return image->pixel(x, y);
 }
 
-/*! Synchronise le contenu de la fenêtre.
- *
+//! Synchronise le contenu de la fenêtre.
+/*!
  * Pour des raisons d'efficacités, le résultat des fonctions de dessin
  * n'est pas affiché immédiatement.  L'appel à sync permet de
  * synchroniser le contenu de la fenêtre.  Autrement dit, cela bloque
@@ -440,15 +559,14 @@ bool DrawingWindow::sync(unsigned long time)
     return synced;
 }
 
-/*! Ferme la fenêtre graphique.
- */
+//! Ferme la fenêtre graphique.
 void DrawingWindow::closeGraph()
 {
     qApp->postEvent(this, new CloseRequestEvent());
 }
 
-/*! Suspend l'exécution pendant un certain temps.
- *
+//! Suspend l'exécution pendant un certain temps.
+/*!
  * \param secs          temps d'attente en seconde
  */
 void DrawingWindow::sleep(unsigned long secs)
@@ -456,8 +574,8 @@ void DrawingWindow::sleep(unsigned long secs)
     DrawingThread::sleep(secs);
 }
 
-/*! Suspend l'exécution pendant un certain temps.
- *
+//! Suspend l'exécution pendant un certain temps.
+/*!
  * \param msecs          temps d'attente en millisecondes
  */
 void DrawingWindow::msleep(unsigned long msecs)
@@ -465,8 +583,8 @@ void DrawingWindow::msleep(unsigned long msecs)
     DrawingThread::msleep(msecs);
 }
 
-/*! Suspend l'exécution pendant un certain temps.
- *
+//! Suspend l'exécution pendant un certain temps.
+/*!
  * \param usecs          temps d'attente en microsecondes
  */
 void DrawingWindow::usleep(unsigned long usecs)
@@ -474,7 +592,8 @@ void DrawingWindow::usleep(unsigned long usecs)
     DrawingThread::usleep(usecs);
 }
 
-/*! \see QWidget
+/*!
+ * \see QWidget
  */
 void DrawingWindow::closeEvent(QCloseEvent *ev)
 {
@@ -493,7 +612,8 @@ void DrawingWindow::closeEvent(QCloseEvent *ev)
     thread->wait();
 }
 
-/*! \see QWidget
+/*!
+ * \see QWidget
  */
 void DrawingWindow::customEvent(QEvent *ev)
 {
@@ -511,7 +631,8 @@ void DrawingWindow::customEvent(QEvent *ev)
     }
 }
 
-/*! \see QWidget
+/*!
+ * \see QWidget
  */
 void DrawingWindow::keyPressEvent(QKeyEvent *ev)
 {
@@ -528,7 +649,8 @@ void DrawingWindow::keyPressEvent(QKeyEvent *ev)
         ev->accept();
 }
 
-/*! \see QWidget
+/*!
+ * \see QWidget
  */
 void DrawingWindow::paintEvent(QPaintEvent *ev)
 {
@@ -540,7 +662,8 @@ void DrawingWindow::paintEvent(QPaintEvent *ev)
     widgetPainter.drawImage(rect, imageCopy, rect);
 }
 
-/*! \see QWidget
+/*!
+ * \see QWidget
  */
 void DrawingWindow::showEvent(QShowEvent *ev)
 {
@@ -551,7 +674,8 @@ void DrawingWindow::showEvent(QShowEvent *ev)
     thread->start_once(QThread::IdlePriority);
 }
 
-/*! \see QWidget
+/*!
+ * \see QWidget
  */
 void DrawingWindow::timerEvent(QTimerEvent *ev)
 {
@@ -565,8 +689,8 @@ void DrawingWindow::timerEvent(QTimerEvent *ev)
 
 //--- DrawingWindow (private methods) ----------------------------------
 
-/*! Fonction d'initialisation.
- *
+//! Fonction d'initialisation.
+/*!
  * Fonction appelée par les différents constructeurs.
  *
  * \param fun           fonction de dessin
@@ -591,8 +715,8 @@ void DrawingWindow::initialize(DrawingWindow::ThreadFunction fun)
     dirtyFlag = false;
 }
 
-/*! Change la couleur de dessin.
- *
+//! Change la couleur de dessin.
+/*!
  * \param color                 couleur
  */
 inline
@@ -603,8 +727,8 @@ void DrawingWindow::setColor(const QColor& color)
     painter->setPen(pen);
 }
 
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
  * \param color                 couleur
  */
 inline
@@ -613,8 +737,8 @@ void DrawingWindow::setBgColor(const QColor& color)
     painter->setBackground(color);
 }
 
-/*! Retourne la couleur de dessin courante.
- *
+//! Retourne la couleur de dessin courante.
+/*!
  * \return              couleur de dessin courante
  */
 inline
@@ -623,8 +747,8 @@ QColor DrawingWindow::getColor()
     return painter->pen().color();
 }
 
-/*! Retourne la couleur de fond courante.
- *
+//! Retourne la couleur de fond courante.
+/*!
  * \return              couleur de fond courante
  */
 inline
@@ -633,8 +757,8 @@ QColor DrawingWindow::getBgColor()
     return painter->background().color();
 }
 
-/*! Verrouille un mutex.
- *
+//! Verrouille un mutex.
+/*!
  * S'assure que le thread courant ne peut pas être terminé s'il
  * détient un mutex.  Pendant de safeUnlock.
  *
@@ -650,8 +774,8 @@ void DrawingWindow::safeLock(QMutex &mutex)
     mutex.lock();
 }
 
-/*! Déverrouille un mutex.
- *
+//! Déverrouille un mutex.
+/*!
  * S'assure que le thread courant ne peut pas être terminé s'il
  * détient un mutex.  Pendant de safeLock.
  *
@@ -667,8 +791,7 @@ void DrawingWindow::safeUnlock(QMutex &mutex)
         thread->setTerminationEnabled(true);
 }
 
-/*! Marque l'image entière comme non à jour.
- */
+//! Marque l'image entière comme non à jour.
 inline
 void DrawingWindow::dirty()
 {
@@ -676,8 +799,8 @@ void DrawingWindow::dirty()
     dirtyRect = image->rect();
 }
 
-/*! Marque un point de l'image comme non à jour.
- *
+//! Marque un point de l'image comme non à jour.
+/*!
  * \param x, y          coordonnées du point
  */
 inline
@@ -686,8 +809,8 @@ void DrawingWindow::dirty(int x, int y)
     dirty(QRect(x, y, 1, 1));
 }
 
-/*! Marque une zone de l'image comme non à jour.
- *
+//! Marque une zone de l'image comme non à jour.
+/*!
  * La zone est définie par un rectangle dont les coordonnées de deux
  * sommets oppposés sont données.
  *
@@ -702,8 +825,8 @@ void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
     dirty(r.normalized());
 }
 
-/*! Marque une zone de l'image comme non à jour.
- *
+//! Marque une zone de l'image comme non à jour.
+/*!
  * \param rect          rectangle délimitant la zone
  */
 void DrawingWindow::dirty(const QRect &rect)
@@ -716,8 +839,8 @@ void DrawingWindow::dirty(const QRect &rect)
     }
 }
 
-/*! Génère un update si besoin.
- *
+//! Génère un update si besoin.
+/*!
  * Génère une demande de mise à jour de la fenêtre (appel à update)
  * s'il y en a besoin.
  */
@@ -732,8 +855,8 @@ void DrawingWindow::mayUpdate()
         update(rect);
 }
 
-/*! Fonction bas-niveau pour sync.
- *
+//! Fonction bas-niveau pour sync.
+/*!
  * Fonction de synchronisation dans le thread principal.
  *
  * \see sync, customEvent
@@ -755,8 +878,8 @@ void DrawingWindow::realSync()
     syncMutex.unlock();
 }
 
-/*! Fonction bas-niveau pour drawText.
- *
+//! Fonction bas-niveau pour drawText.
+/*!
  * Le rendu de texte doit être fait dans le thread principal.  D'où
  * les manipulations tordues et la synchronisation qui s'en suit.
  *
@@ -802,8 +925,7 @@ void DrawingWindow::realDrawText(int x, int y, const char *text, int flags)
 
 //--- DrawingThread ----------------------------------------------------
 
-/*! Constructeur.
- */
+//! Constructeur.
 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
     : drawingWindow(w)
     , threadFunction(f)
@@ -811,8 +933,7 @@ DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
 {
 }
 
-/*! Démarre le thread si ce n'a pas encore été fait.
- */
+//! Démarre le thread si ce n'a pas encore été fait.
 void DrawingThread::start_once(Priority priority)
 {
     if (!started_once) {
@@ -821,8 +942,7 @@ void DrawingThread::start_once(Priority priority)
     }
 }
 
-/*! La vraie fonction pour le thread.
- */
+//! La vraie fonction pour le thread.
 void DrawingThread::run()
 {
     threadFunction(drawingWindow);