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