Generated on Fri Oct 19 11:24:59 2018 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 quarterNodeWidth = halfNodeWidth / 2.0;
00059   const double failedWidth = 14.0;
00060   const double halfFailedWidth = failedWidth / 2.0;
00061   const double quarterFailedWidthF = failedWidth / 4.0;
00062   const double shadowOffset = 3.0;
00063   const double hiddenDepth =
00064     static_cast<double>(Layout::dist_y) + failedWidth;
00065 
00066   DrawingCursor::DrawingCursor(VisualNode* root,
00067                                const VisualNode::NodeAllocator& na,
00068                                BestNode* curBest0,
00069                                QPainter& painter0,
00070                                const QRect& clippingRect0, bool showCopies)
00071     : NodeCursor<VisualNode>(root,na), painter(painter0),
00072       clippingRect(clippingRect0), curBest(curBest0),
00073       x(0.0), y(0.0), copies(showCopies) {
00074     QPen pen = painter.pen();
00075     pen.setWidth(1);
00076     painter.setPen(pen);
00077   }
00078 
00079   void
00080   DrawingCursor::processCurrentNode(void) {
00081     Gist::VisualNode* n = node();
00082     double parentX = x - static_cast<double>(n->getOffset());
00083     double parentY = y - static_cast<double>(Layout::dist_y) + nodeWidth;
00084     if (!n->isRoot() &&
00085         (n->getParent(na)->getStatus() == STOP ||
00086          n->getParent(na)->getStatus() == UNSTOP) )
00087       parentY -= (nodeWidth-failedWidth)/2;
00088 
00089     double myx = x;
00090     double myy = y;
00091 
00092     if (n->getStatus() == STOP || n->getStatus() == UNSTOP)
00093       myy += (nodeWidth-failedWidth)/2;
00094 
00095     if (n != startNode()) {
00096       if (n->isOnPath())
00097         painter.setPen(Qt::red);
00098       else
00099         painter.setPen(Qt::black);
00100       // Here we use drawPath instead of drawLine in order to
00101       // workaround a strange redraw artefact on Windows
00102       QPainterPath path;
00103       path.moveTo(myx,myy);
00104       path.lineTo(parentX,parentY);
00105       painter.drawPath(path);
00106 
00107       QFontMetrics fm = painter.fontMetrics();
00108       QString label = na.getLabel(n);
00109       int alt = n->getAlternative(na);
00110       int n_alt = n->getParent(na)->getNumberOfChildren();
00111       int tw = fm.width(label);
00112       int lx;
00113       if (alt==0 && n_alt > 1) {
00114         lx = myx-tw-4;
00115       } else if (alt==n_alt-1 && n_alt > 1) {
00116         lx = myx+4;
00117       } else {
00118         lx = myx-tw/2;
00119       }
00120       painter.drawText(QPointF(lx,myy-2),label);
00121     }
00122 
00123     // draw shadow
00124     if (n->isMarked()) {
00125       painter.setBrush(Qt::gray);
00126       painter.setPen(Qt::NoPen);
00127       if (n->isHidden()) {
00128         QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset),
00129                              QPointF(myx+nodeWidth+shadowOffset,
00130                                      myy+hiddenDepth+shadowOffset),
00131                              QPointF(myx-nodeWidth+shadowOffset,
00132                                      myy+hiddenDepth+shadowOffset),
00133                             };
00134         painter.drawConvexPolygon(points, 3);
00135 
00136       } else {
00137         switch (n->getStatus()) {
00138         case Gist::SOLVED:
00139           {
00140             QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset),
00141                                  QPointF(myx+halfNodeWidth+shadowOffset,
00142                                          myy+halfNodeWidth+shadowOffset),
00143                                  QPointF(myx+shadowOffset,
00144                                          myy+nodeWidth+shadowOffset),
00145                                  QPointF(myx-halfNodeWidth+shadowOffset,
00146                                          myy+halfNodeWidth+shadowOffset)
00147                                 };
00148             painter.drawConvexPolygon(points, 4);
00149           }
00150           break;
00151         case Gist::FAILED:
00152           painter.drawRect(myx-halfFailedWidth+shadowOffset,
00153                            myy+shadowOffset, failedWidth, failedWidth);
00154           break;
00155         case Gist::UNSTOP:
00156         case Gist::STOP:
00157           {
00158             QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF,
00159                                          myy+shadowOffset),
00160                                  QPointF(myx+shadowOffset+quarterFailedWidthF,
00161                                          myy+shadowOffset),
00162                                  QPointF(myx+shadowOffset+halfFailedWidth,
00163                                          myy+shadowOffset
00164                                             +quarterFailedWidthF),
00165                                  QPointF(myx+shadowOffset+halfFailedWidth,
00166                                          myy+shadowOffset+halfFailedWidth+
00167                                              quarterFailedWidthF),
00168                                  QPointF(myx+shadowOffset+quarterFailedWidthF,
00169                                          myy+shadowOffset+failedWidth),
00170                                  QPointF(myx+shadowOffset-quarterFailedWidthF,
00171                                          myy+shadowOffset+failedWidth),
00172                                  QPointF(myx+shadowOffset-halfFailedWidth,
00173                                          myy+shadowOffset+halfFailedWidth+
00174                                              quarterFailedWidthF),
00175                                  QPointF(myx+shadowOffset-halfFailedWidth,
00176                                          myy+shadowOffset
00177                                             +quarterFailedWidthF),
00178                                 };
00179             painter.drawConvexPolygon(points, 8);
00180           }
00181           break;
00182         case Gist::BRANCH:
00183           painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
00184                               myy+shadowOffset, nodeWidth, nodeWidth);
00185           break;
00186         case Gist::UNDETERMINED:
00187           painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
00188                               myy+shadowOffset, nodeWidth, nodeWidth);
00189           break;
00190         }
00191       }
00192     }
00193 
00194     painter.setPen(Qt::SolidLine);
00195     if (n->isHidden()) {
00196       if (n->hasOpenChildren()) {
00197         QLinearGradient gradient(myx-nodeWidth,myy,
00198                                  myx+nodeWidth*1.3,myy+hiddenDepth*1.3);
00199         if (n->hasSolvedChildren()) {
00200           gradient.setColorAt(0, white);
00201           gradient.setColorAt(1, green);
00202         } else if (n->hasFailedChildren()) {
00203           gradient.setColorAt(0, white);
00204           gradient.setColorAt(1, red);
00205         } else {
00206           gradient.setColorAt(0, white);
00207           gradient.setColorAt(1, QColor(0,0,0));
00208         }
00209         painter.setBrush(gradient);
00210       } else {
00211         if (n->hasSolvedChildren())
00212           painter.setBrush(QBrush(green));
00213         else
00214           painter.setBrush(QBrush(red));
00215       }
00216 
00217       QPointF points[3] = {QPointF(myx,myy),
00218                            QPointF(myx+nodeWidth,myy+hiddenDepth),
00219                            QPointF(myx-nodeWidth,myy+hiddenDepth),
00220                           };
00221       painter.drawConvexPolygon(points, 3);
00222     } else {
00223       switch (n->getStatus()) {
00224       case Gist::SOLVED:
00225         {
00226           if (n->isCurrentBest(curBest)) {
00227             painter.setBrush(QBrush(orange));
00228           } else {
00229             painter.setBrush(QBrush(green));
00230           }
00231           QPointF points[4] = {QPointF(myx,myy),
00232                                QPointF(myx+halfNodeWidth,myy+halfNodeWidth),
00233                                QPointF(myx,myy+nodeWidth),
00234                                QPointF(myx-halfNodeWidth,myy+halfNodeWidth)
00235                               };
00236           painter.drawConvexPolygon(points, 4);
00237         }
00238         break;
00239       case Gist::FAILED:
00240         painter.setBrush(QBrush(red));
00241         painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth);
00242         break;
00243       case Gist::UNSTOP:
00244       case Gist::STOP:
00245         {
00246           painter.setBrush(n->getStatus() == STOP ?
00247                            QBrush(red) : QBrush(green));
00248           QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy),
00249                                QPointF(myx+quarterFailedWidthF,myy),
00250                                QPointF(myx+halfFailedWidth,
00251                                        myy+quarterFailedWidthF),
00252                                QPointF(myx+halfFailedWidth,
00253                                        myy+halfFailedWidth+
00254                                            quarterFailedWidthF),
00255                                QPointF(myx+quarterFailedWidthF,
00256                                        myy+failedWidth),
00257                                QPointF(myx-quarterFailedWidthF,
00258                                        myy+failedWidth),
00259                                QPointF(myx-halfFailedWidth,
00260                                        myy+halfFailedWidth+
00261                                            quarterFailedWidthF),
00262                                QPointF(myx-halfFailedWidth,
00263                                        myy+quarterFailedWidthF),
00264                               };
00265           painter.drawConvexPolygon(points, 8);
00266         }
00267         break;
00268       case Gist::BRANCH:
00269         painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) :
00270                                                      QBrush(white));
00271         painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
00272         break;
00273       case Gist::UNDETERMINED:
00274         painter.setBrush(Qt::white);
00275         painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
00276         break;
00277       }
00278     }
00279 
00280     if (copies && (n->hasCopy() && !n->hasWorkingSpace())) {
00281      painter.setBrush(Qt::darkRed);
00282      painter.drawEllipse(myx, myy, 10.0, 10.0);
00283     }
00284 
00285     if (copies && n->hasWorkingSpace()) {
00286      painter.setBrush(Qt::darkYellow);
00287      painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0);
00288     }
00289 
00290     if (n->isBookmarked()) {
00291      painter.setBrush(Qt::black);
00292      painter.drawEllipse(myx-10-0, myy, 10.0, 10.0);
00293     }
00294 
00295   }
00296 
00297 }}
00298 
00299 // STATISTICS: gist-any