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: 2010-04-21 14:22:14 +0200 (Wed, 21 Apr 2010) $ by $Author: tack $ 00011 * $Revision: 10784 $ 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 int nodeWidth = 20; 00061 const int halfNodeWidth = nodeWidth / 2; 00062 const int quarterNodeWidth = halfNodeWidth / 2; 00063 const int failedWidth = 14; 00064 const int halfFailedWidth = failedWidth / 2; 00065 const float quarterFailedWidthF = static_cast<float>(failedWidth) / 4.0; 00066 const int shadowOffset = 3; 00067 const int dSolvedOffset = nodeWidth / 6; 00068 const int dSolvedHalfWidth = (nodeWidth-2*dSolvedOffset) / 2; 00069 const int hiddenDepth = Layout::dist_y + failedWidth; 00070 00071 DrawingCursor::DrawingCursor(Gist::VisualNode* root, BestNode* curBest0, 00072 QPainter& painter0, 00073 const QRect& clippingRect0, bool showCopies) 00074 : NodeCursor<VisualNode>(root), painter(painter0), 00075 clippingRect(clippingRect0), curBest(curBest0), 00076 x(0), y(0), copies(showCopies) { 00077 QPen pen = painter.pen(); 00078 pen.setWidth(1); 00079 painter.setPen(pen); 00080 } 00081 00082 bool 00083 DrawingCursor::isClipped(void) { 00084 if (clippingRect.width() == 0 && clippingRect.x() == 0 00085 && clippingRect.height() == 0 && clippingRect.y() == 0) 00086 return false; 00087 BoundingBox b = node()->getBoundingBox(); 00088 return (x + b.left > clippingRect.x() + clippingRect.width() || 00089 x + b.right < clippingRect.x() || 00090 y > clippingRect.y() + clippingRect.height() || 00091 y + (node()->getShape()->depth()+1) * Layout::dist_y < 00092 clippingRect.y()); 00093 } 00094 00095 void 00096 DrawingCursor::processCurrentNode(void) { 00097 Gist::VisualNode* n = node(); 00098 int parentX = x - (n->getOffset()); 00099 int parentY = y - Layout::dist_y + nodeWidth; 00100 if (n->getParent() != NULL && 00101 (n->getParent()->getStatus() == STOP || 00102 n->getParent()->getStatus() == UNSTOP) ) 00103 parentY -= (nodeWidth-failedWidth)/2; 00104 00105 int myx = x; 00106 int myy = y; 00107 00108 if (n->getStatus() == STOP || n->getStatus() == UNSTOP) 00109 myy += (nodeWidth-failedWidth)/2; 00110 00111 if (n != startNode()) { 00112 if (n->isOnPath()) 00113 painter.setPen(Qt::red); 00114 else 00115 painter.setPen(Qt::black); 00116 QPainterPath path; 00117 path.moveTo(myx,myy); 00118 path.lineTo(parentX,parentY); 00119 painter.drawPath(path); 00120 } 00121 00122 // draw shadow 00123 if (n->isMarked()) { 00124 painter.setBrush(Qt::gray); 00125 painter.setPen(Qt::NoPen); 00126 if (n->isHidden()) { 00127 QPoint points[3] = {QPoint(myx+shadowOffset,myy+shadowOffset), 00128 QPoint(myx+nodeWidth+shadowOffset, 00129 myy+hiddenDepth+shadowOffset), 00130 QPoint(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 QPoint points[4] = {QPoint(myx+shadowOffset,myy+shadowOffset), 00140 QPoint(myx+halfNodeWidth+shadowOffset, 00141 myy+halfNodeWidth+shadowOffset), 00142 QPoint(myx+shadowOffset, 00143 myy+nodeWidth+shadowOffset), 00144 QPoint(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,myx+nodeWidth*1.3,myy+hiddenDepth*1.3); 00197 if (n->hasSolvedChildren()) { 00198 gradient.setColorAt(0, white); 00199 gradient.setColorAt(1, green); 00200 } else if (n->hasFailedChildren()) { 00201 gradient.setColorAt(0, white); 00202 gradient.setColorAt(1, red); 00203 } else { 00204 gradient.setColorAt(0, white); 00205 gradient.setColorAt(1, QColor(0,0,0)); 00206 } 00207 painter.setBrush(gradient); 00208 } else { 00209 if (n->hasSolvedChildren()) 00210 painter.setBrush(QBrush(green)); 00211 else 00212 painter.setBrush(QBrush(red)); 00213 } 00214 00215 QPoint points[3] = {QPoint(myx,myy), 00216 QPoint(myx+nodeWidth,myy+hiddenDepth), 00217 QPoint(myx-nodeWidth,myy+hiddenDepth), 00218 }; 00219 painter.drawConvexPolygon(points, 3); 00220 } else { 00221 switch (n->getStatus()) { 00222 case Gist::SOLVED: 00223 { 00224 if (n->isCurrentBest(curBest)) { 00225 painter.setBrush(QBrush(orange)); 00226 } else { 00227 painter.setBrush(QBrush(green)); 00228 } 00229 QPoint points[4] = {QPoint(myx,myy), 00230 QPoint(myx+halfNodeWidth,myy+halfNodeWidth), 00231 QPoint(myx,myy+nodeWidth), 00232 QPoint(myx-halfNodeWidth,myy+halfNodeWidth) 00233 }; 00234 painter.drawConvexPolygon(points, 4); 00235 } 00236 break; 00237 case Gist::FAILED: 00238 painter.setBrush(QBrush(red)); 00239 painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth); 00240 break; 00241 case Gist::UNSTOP: 00242 case Gist::STOP: 00243 { 00244 painter.setBrush(n->getStatus() == STOP ? 00245 QBrush(red) : QBrush(green)); 00246 QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy), 00247 QPointF(myx+quarterFailedWidthF,myy), 00248 QPointF(myx+halfFailedWidth, 00249 myy+quarterFailedWidthF), 00250 QPointF(myx+halfFailedWidth, 00251 myy+halfFailedWidth+ 00252 quarterFailedWidthF), 00253 QPointF(myx+quarterFailedWidthF, 00254 myy+failedWidth), 00255 QPointF(myx-quarterFailedWidthF, 00256 myy+failedWidth), 00257 QPointF(myx-halfFailedWidth, 00258 myy+halfFailedWidth+ 00259 quarterFailedWidthF), 00260 QPointF(myx-halfFailedWidth, 00261 myy+quarterFailedWidthF), 00262 }; 00263 painter.drawConvexPolygon(points, 8); 00264 } 00265 break; 00266 case Gist::BRANCH: 00267 painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) : 00268 QBrush(white)); 00269 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth); 00270 break; 00271 case Gist::UNDETERMINED: 00272 painter.setBrush(Qt::white); 00273 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth); 00274 break; 00275 } 00276 00277 } 00278 00279 if (copies && n->hasCopy()) { 00280 painter.setBrush(Qt::darkRed); 00281 painter.drawEllipse(myx, myy, 10, 10); 00282 } 00283 00284 if (copies && n->hasWorkingSpace()) { 00285 painter.setBrush(Qt::darkYellow); 00286 painter.drawEllipse(myx, myy + 10, 10, 10); 00287 } 00288 00289 if (n->isBookmarked()) { 00290 painter.setBrush(Qt::black); 00291 painter.drawEllipse(myx-10, myy, 10, 10); 00292 } 00293 00294 } 00295 00296 }} 00297 00298 // STATISTICS: gist-any