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-08-12 09:48:30 +0200 (Thu, 12 Aug 2010) $ by $Author: tack $ 00011 * $Revision: 11345 $ 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 00112 // draw shadow 00113 if (n->isMarked()) { 00114 painter.setBrush(Qt::gray); 00115 painter.setPen(Qt::NoPen); 00116 if (n->isHidden()) { 00117 QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset), 00118 QPointF(myx+nodeWidth+shadowOffset, 00119 myy+hiddenDepth+shadowOffset), 00120 QPointF(myx-nodeWidth+shadowOffset, 00121 myy+hiddenDepth+shadowOffset), 00122 }; 00123 painter.drawConvexPolygon(points, 3); 00124 00125 } else { 00126 switch (n->getStatus()) { 00127 case Gist::SOLVED: 00128 { 00129 QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset), 00130 QPointF(myx+halfNodeWidth+shadowOffset, 00131 myy+halfNodeWidth+shadowOffset), 00132 QPointF(myx+shadowOffset, 00133 myy+nodeWidth+shadowOffset), 00134 QPointF(myx-halfNodeWidth+shadowOffset, 00135 myy+halfNodeWidth+shadowOffset) 00136 }; 00137 painter.drawConvexPolygon(points, 4); 00138 } 00139 break; 00140 case Gist::FAILED: 00141 painter.drawRect(myx-halfFailedWidth+shadowOffset, 00142 myy+shadowOffset, failedWidth, failedWidth); 00143 break; 00144 case Gist::UNSTOP: 00145 case Gist::STOP: 00146 { 00147 QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF, 00148 myy+shadowOffset), 00149 QPointF(myx+shadowOffset+quarterFailedWidthF, 00150 myy+shadowOffset), 00151 QPointF(myx+shadowOffset+halfFailedWidth, 00152 myy+shadowOffset 00153 +quarterFailedWidthF), 00154 QPointF(myx+shadowOffset+halfFailedWidth, 00155 myy+shadowOffset+halfFailedWidth+ 00156 quarterFailedWidthF), 00157 QPointF(myx+shadowOffset+quarterFailedWidthF, 00158 myy+shadowOffset+failedWidth), 00159 QPointF(myx+shadowOffset-quarterFailedWidthF, 00160 myy+shadowOffset+failedWidth), 00161 QPointF(myx+shadowOffset-halfFailedWidth, 00162 myy+shadowOffset+halfFailedWidth+ 00163 quarterFailedWidthF), 00164 QPointF(myx+shadowOffset-halfFailedWidth, 00165 myy+shadowOffset 00166 +quarterFailedWidthF), 00167 }; 00168 painter.drawConvexPolygon(points, 8); 00169 } 00170 break; 00171 case Gist::BRANCH: 00172 painter.drawEllipse(myx-halfNodeWidth+shadowOffset, 00173 myy+shadowOffset, nodeWidth, nodeWidth); 00174 break; 00175 case Gist::UNDETERMINED: 00176 painter.drawEllipse(myx-halfNodeWidth+shadowOffset, 00177 myy+shadowOffset, nodeWidth, nodeWidth); 00178 break; 00179 } 00180 } 00181 } 00182 00183 painter.setPen(Qt::SolidLine); 00184 if (n->isHidden()) { 00185 if (n->hasOpenChildren()) { 00186 QLinearGradient gradient(myx-nodeWidth,myy, 00187 myx+nodeWidth*1.3,myy+hiddenDepth*1.3); 00188 if (n->hasSolvedChildren()) { 00189 gradient.setColorAt(0, white); 00190 gradient.setColorAt(1, green); 00191 } else if (n->hasFailedChildren()) { 00192 gradient.setColorAt(0, white); 00193 gradient.setColorAt(1, red); 00194 } else { 00195 gradient.setColorAt(0, white); 00196 gradient.setColorAt(1, QColor(0,0,0)); 00197 } 00198 painter.setBrush(gradient); 00199 } else { 00200 if (n->hasSolvedChildren()) 00201 painter.setBrush(QBrush(green)); 00202 else 00203 painter.setBrush(QBrush(red)); 00204 } 00205 00206 QPointF points[3] = {QPointF(myx,myy), 00207 QPointF(myx+nodeWidth,myy+hiddenDepth), 00208 QPointF(myx-nodeWidth,myy+hiddenDepth), 00209 }; 00210 painter.drawConvexPolygon(points, 3); 00211 } else { 00212 switch (n->getStatus()) { 00213 case Gist::SOLVED: 00214 { 00215 if (n->isCurrentBest(curBest)) { 00216 painter.setBrush(QBrush(orange)); 00217 } else { 00218 painter.setBrush(QBrush(green)); 00219 } 00220 QPointF points[4] = {QPointF(myx,myy), 00221 QPointF(myx+halfNodeWidth,myy+halfNodeWidth), 00222 QPointF(myx,myy+nodeWidth), 00223 QPointF(myx-halfNodeWidth,myy+halfNodeWidth) 00224 }; 00225 painter.drawConvexPolygon(points, 4); 00226 } 00227 break; 00228 case Gist::FAILED: 00229 painter.setBrush(QBrush(red)); 00230 painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth); 00231 break; 00232 case Gist::UNSTOP: 00233 case Gist::STOP: 00234 { 00235 painter.setBrush(n->getStatus() == STOP ? 00236 QBrush(red) : QBrush(green)); 00237 QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy), 00238 QPointF(myx+quarterFailedWidthF,myy), 00239 QPointF(myx+halfFailedWidth, 00240 myy+quarterFailedWidthF), 00241 QPointF(myx+halfFailedWidth, 00242 myy+halfFailedWidth+ 00243 quarterFailedWidthF), 00244 QPointF(myx+quarterFailedWidthF, 00245 myy+failedWidth), 00246 QPointF(myx-quarterFailedWidthF, 00247 myy+failedWidth), 00248 QPointF(myx-halfFailedWidth, 00249 myy+halfFailedWidth+ 00250 quarterFailedWidthF), 00251 QPointF(myx-halfFailedWidth, 00252 myy+quarterFailedWidthF), 00253 }; 00254 painter.drawConvexPolygon(points, 8); 00255 } 00256 break; 00257 case Gist::BRANCH: 00258 painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) : 00259 QBrush(white)); 00260 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth); 00261 break; 00262 case Gist::UNDETERMINED: 00263 painter.setBrush(Qt::white); 00264 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth); 00265 break; 00266 } 00267 } 00268 00269 if (copies && (n->hasCopy() && !n->hasWorkingSpace())) { 00270 painter.setBrush(Qt::darkRed); 00271 painter.drawEllipse(myx, myy, 10.0, 10.0); 00272 } 00273 00274 if (copies && n->hasWorkingSpace()) { 00275 painter.setBrush(Qt::darkYellow); 00276 painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0); 00277 } 00278 00279 if (n->isBookmarked()) { 00280 painter.setBrush(Qt::black); 00281 painter.drawEllipse(myx-10-0, myy, 10.0, 10.0); 00282 } 00283 00284 } 00285 00286 }} 00287 00288 // STATISTICS: gist-any