Generated on Thu Apr 11 13:59:03 2019 for Gecode by doxygen 1.6.3

drawingcursor.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Guido Tack, 2006
00008  *
00009  *  This file is part of Gecode, the generic constraint
00010  *  development environment:
00011  *     http://www.gecode.org
00012  *
00013  * Permission is hereby granted, free of charge, to any person obtaining
00014  * a copy of this software and associated documentation files (the
00015  * "Software"), to deal in the Software without restriction, including
00016  * without limitation the rights to use, copy, modify, merge, publish,
00017  * distribute, sublicense, and/or sell copies of the Software, and to
00018  * permit persons to whom the Software is furnished to do so, subject to
00019  * the following conditions:
00020  *
00021  * The above copyright notice and this permission notice shall be
00022  * included in all copies or substantial portions of the Software.
00023  *
00024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00028  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00029  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00030  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00031  *
00032  */
00033 
00034 #include <gecode/gist/drawingcursor.hh>
00035 
00036 namespace Gecode { namespace Gist {
00037 
00039   const QColor DrawingCursor::red(218, 37, 29);
00041   const QColor DrawingCursor::green(11, 118, 70);
00043   const QColor DrawingCursor::blue(0, 92, 161);
00045   const QColor DrawingCursor::orange(235, 137, 27);
00047   const QColor DrawingCursor::white(255,255,255);
00048 
00050   const QColor DrawingCursor::lightRed(218, 37, 29, 120);
00052   const QColor DrawingCursor::lightGreen(11, 118, 70, 120);
00054   const QColor DrawingCursor::lightBlue(0, 92, 161, 120);
00055 
00056   const double nodeWidth = 20.0;
00057   const double halfNodeWidth = nodeWidth / 2.0;
00058   const double failedWidth = 14.0;
00059   const double halfFailedWidth = failedWidth / 2.0;
00060   const double quarterFailedWidthF = failedWidth / 4.0;
00061   const double shadowOffset = 3.0;
00062   const double hiddenDepth =
00063     static_cast<double>(Layout::dist_y) + failedWidth;
00064 
00065   DrawingCursor::DrawingCursor(VisualNode* root,
00066                                const VisualNode::NodeAllocator& na,
00067                                BestNode* curBest0,
00068                                QPainter& painter0,
00069                                const QRect& clippingRect0, bool showCopies)
00070     : NodeCursor<VisualNode>(root,na), painter(painter0),
00071       clippingRect(clippingRect0), curBest(curBest0),
00072       x(0.0), y(0.0), copies(showCopies) {
00073     QPen pen = painter.pen();
00074     pen.setWidth(1);
00075     painter.setPen(pen);
00076   }
00077 
00078   void
00079   DrawingCursor::processCurrentNode(void) {
00080     Gist::VisualNode* n = node();
00081     double parentX = x - static_cast<double>(n->getOffset());
00082     double parentY = y - static_cast<double>(Layout::dist_y) + nodeWidth;
00083     if (!n->isRoot() &&
00084         (n->getParent(na)->getStatus() == STOP ||
00085          n->getParent(na)->getStatus() == UNSTOP) )
00086       parentY -= (nodeWidth-failedWidth)/2;
00087 
00088     double myx = x;
00089     double myy = y;
00090 
00091     if (n->getStatus() == STOP || n->getStatus() == UNSTOP)
00092       myy += (nodeWidth-failedWidth)/2;
00093 
00094     if (n != startNode()) {
00095       if (n->isOnPath())
00096         painter.setPen(Qt::red);
00097       else
00098         painter.setPen(Qt::black);
00099       // Here we use drawPath instead of drawLine in order to
00100       // workaround a strange redraw artefact on Windows
00101       QPainterPath path;
00102       path.moveTo(myx,myy);
00103       path.lineTo(parentX,parentY);
00104       painter.drawPath(path);
00105 
00106       QFontMetrics fm = painter.fontMetrics();
00107       QString label = na.getLabel(n);
00108       int alt = n->getAlternative(na);
00109       int n_alt = n->getParent(na)->getNumberOfChildren();
00110       int tw = fm.width(label);
00111       int lx;
00112       if (alt==0 && n_alt > 1) {
00113         lx = myx-tw-4;
00114       } else if (alt==n_alt-1 && n_alt > 1) {
00115         lx = myx+4;
00116       } else {
00117         lx = myx-tw/2;
00118       }
00119       painter.drawText(QPointF(lx,myy-2),label);
00120     }
00121 
00122     // draw shadow
00123     if (n->isMarked()) {
00124       painter.setBrush(Qt::gray);
00125       painter.setPen(Qt::NoPen);
00126       if (n->isHidden()) {
00127         QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset),
00128                              QPointF(myx+nodeWidth+shadowOffset,
00129                                      myy+hiddenDepth+shadowOffset),
00130                              QPointF(myx-nodeWidth+shadowOffset,
00131                                      myy+hiddenDepth+shadowOffset),
00132                             };
00133         painter.drawConvexPolygon(points, 3);
00134 
00135       } else {
00136         switch (n->getStatus()) {
00137         case Gist::SOLVED:
00138           {
00139             QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset),
00140                                  QPointF(myx+halfNodeWidth+shadowOffset,
00141                                          myy+halfNodeWidth+shadowOffset),
00142                                  QPointF(myx+shadowOffset,
00143                                          myy+nodeWidth+shadowOffset),
00144                                  QPointF(myx-halfNodeWidth+shadowOffset,
00145                                          myy+halfNodeWidth+shadowOffset)
00146                                 };
00147             painter.drawConvexPolygon(points, 4);
00148           }
00149           break;
00150         case Gist::FAILED:
00151           painter.drawRect(myx-halfFailedWidth+shadowOffset,
00152                            myy+shadowOffset, failedWidth, failedWidth);
00153           break;
00154         case Gist::UNSTOP:
00155         case Gist::STOP:
00156           {
00157             QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF,
00158                                          myy+shadowOffset),
00159                                  QPointF(myx+shadowOffset+quarterFailedWidthF,
00160                                          myy+shadowOffset),
00161                                  QPointF(myx+shadowOffset+halfFailedWidth,
00162                                          myy+shadowOffset
00163                                             +quarterFailedWidthF),
00164                                  QPointF(myx+shadowOffset+halfFailedWidth,
00165                                          myy+shadowOffset+halfFailedWidth+
00166                                              quarterFailedWidthF),
00167                                  QPointF(myx+shadowOffset+quarterFailedWidthF,
00168                                          myy+shadowOffset+failedWidth),
00169                                  QPointF(myx+shadowOffset-quarterFailedWidthF,
00170                                          myy+shadowOffset+failedWidth),
00171                                  QPointF(myx+shadowOffset-halfFailedWidth,
00172                                          myy+shadowOffset+halfFailedWidth+
00173                                              quarterFailedWidthF),
00174                                  QPointF(myx+shadowOffset-halfFailedWidth,
00175                                          myy+shadowOffset
00176                                             +quarterFailedWidthF),
00177                                 };
00178             painter.drawConvexPolygon(points, 8);
00179           }
00180           break;
00181         case Gist::BRANCH:
00182           painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
00183                               myy+shadowOffset, nodeWidth, nodeWidth);
00184           break;
00185         case Gist::UNDETERMINED:
00186           painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
00187                               myy+shadowOffset, nodeWidth, nodeWidth);
00188           break;
00189         }
00190       }
00191     }
00192 
00193     painter.setPen(Qt::SolidLine);
00194     if (n->isHidden()) {
00195       if (n->hasOpenChildren()) {
00196         QLinearGradient gradient(myx-nodeWidth,myy,
00197                                  myx+nodeWidth*1.3,myy+hiddenDepth*1.3);
00198         if (n->hasSolvedChildren()) {
00199           gradient.setColorAt(0, white);
00200           gradient.setColorAt(1, green);
00201         } else if (n->hasFailedChildren()) {
00202           gradient.setColorAt(0, white);
00203           gradient.setColorAt(1, red);
00204         } else {
00205           gradient.setColorAt(0, white);
00206           gradient.setColorAt(1, QColor(0,0,0));
00207         }
00208         painter.setBrush(gradient);
00209       } else {
00210         if (n->hasSolvedChildren())
00211           painter.setBrush(QBrush(green));
00212         else
00213           painter.setBrush(QBrush(red));
00214       }
00215 
00216       QPointF points[3] = {QPointF(myx,myy),
00217                            QPointF(myx+nodeWidth,myy+hiddenDepth),
00218                            QPointF(myx-nodeWidth,myy+hiddenDepth),
00219                           };
00220       painter.drawConvexPolygon(points, 3);
00221     } else {
00222       switch (n->getStatus()) {
00223       case Gist::SOLVED:
00224         {
00225           if (n->isCurrentBest(curBest)) {
00226             painter.setBrush(QBrush(orange));
00227           } else {
00228             painter.setBrush(QBrush(green));
00229           }
00230           QPointF points[4] = {QPointF(myx,myy),
00231                                QPointF(myx+halfNodeWidth,myy+halfNodeWidth),
00232                                QPointF(myx,myy+nodeWidth),
00233                                QPointF(myx-halfNodeWidth,myy+halfNodeWidth)
00234                               };
00235           painter.drawConvexPolygon(points, 4);
00236         }
00237         break;
00238       case Gist::FAILED:
00239         painter.setBrush(QBrush(red));
00240         painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth);
00241         break;
00242       case Gist::UNSTOP:
00243       case Gist::STOP:
00244         {
00245           painter.setBrush(n->getStatus() == STOP ?
00246                            QBrush(red) : QBrush(green));
00247           QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy),
00248                                QPointF(myx+quarterFailedWidthF,myy),
00249                                QPointF(myx+halfFailedWidth,
00250                                        myy+quarterFailedWidthF),
00251                                QPointF(myx+halfFailedWidth,
00252                                        myy+halfFailedWidth+
00253                                            quarterFailedWidthF),
00254                                QPointF(myx+quarterFailedWidthF,
00255                                        myy+failedWidth),
00256                                QPointF(myx-quarterFailedWidthF,
00257                                        myy+failedWidth),
00258                                QPointF(myx-halfFailedWidth,
00259                                        myy+halfFailedWidth+
00260                                            quarterFailedWidthF),
00261                                QPointF(myx-halfFailedWidth,
00262                                        myy+quarterFailedWidthF),
00263                               };
00264           painter.drawConvexPolygon(points, 8);
00265         }
00266         break;
00267       case Gist::BRANCH:
00268         painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) :
00269                                                      QBrush(white));
00270         painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
00271         break;
00272       case Gist::UNDETERMINED:
00273         painter.setBrush(Qt::white);
00274         painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
00275         break;
00276       }
00277     }
00278 
00279     if (copies && (n->hasCopy() && !n->hasWorkingSpace())) {
00280      painter.setBrush(Qt::darkRed);
00281      painter.drawEllipse(myx, myy, 10.0, 10.0);
00282     }
00283 
00284     if (copies && n->hasWorkingSpace()) {
00285      painter.setBrush(Qt::darkYellow);
00286      painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0);
00287     }
00288 
00289     if (n->isBookmarked()) {
00290      painter.setBrush(Qt::black);
00291      painter.drawEllipse(myx-10-0, myy, 10.0, 10.0);
00292     }
00293 
00294   }
00295 
00296 }}
00297 
00298 // STATISTICS: gist-any