this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Guido Tack <tack@gecode.org> 5 * 6 * Copyright: 7 * Guido Tack, 2006 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34#include <gecode/gist/drawingcursor.hh> 35 36namespace Gecode { namespace Gist { 37 38 /// Red color for failed nodes 39 const QColor DrawingCursor::red(218, 37, 29); 40 /// Green color for solved nodes 41 const QColor DrawingCursor::green(11, 118, 70); 42 /// Blue color for choice nodes 43 const QColor DrawingCursor::blue(0, 92, 161); 44 /// Orange color for best solutions 45 const QColor DrawingCursor::orange(235, 137, 27); 46 /// White color 47 const QColor DrawingCursor::white(255,255,255); 48 49 /// Red color for expanded failed nodes 50 const QColor DrawingCursor::lightRed(218, 37, 29, 120); 51 /// Green color for expanded solved nodes 52 const QColor DrawingCursor::lightGreen(11, 118, 70, 120); 53 /// Blue color for expanded choice nodes 54 const QColor DrawingCursor::lightBlue(0, 92, 161, 120); 55 56 const double nodeWidth = 20.0; 57 const double halfNodeWidth = nodeWidth / 2.0; 58 const double failedWidth = 14.0; 59 const double halfFailedWidth = failedWidth / 2.0; 60 const double quarterFailedWidthF = failedWidth / 4.0; 61 const double shadowOffset = 3.0; 62 const double hiddenDepth = 63 static_cast<double>(Layout::dist_y) + failedWidth; 64 65 DrawingCursor::DrawingCursor(VisualNode* root, 66 const VisualNode::NodeAllocator& na, 67 BestNode* curBest0, 68 QPainter& painter0, 69 const QRect& clippingRect0, bool showCopies) 70 : NodeCursor<VisualNode>(root,na), painter(painter0), 71 clippingRect(clippingRect0), curBest(curBest0), 72 x(0.0), y(0.0), copies(showCopies) { 73 QPen pen = painter.pen(); 74 pen.setWidth(1); 75 painter.setPen(pen); 76 } 77 78 void 79 DrawingCursor::processCurrentNode(void) { 80 Gist::VisualNode* n = node(); 81 double parentX = x - static_cast<double>(n->getOffset()); 82 double parentY = y - static_cast<double>(Layout::dist_y) + nodeWidth; 83 if (!n->isRoot() && 84 (n->getParent(na)->getStatus() == STOP || 85 n->getParent(na)->getStatus() == UNSTOP) ) 86 parentY -= (nodeWidth-failedWidth)/2; 87 88 double myx = x; 89 double myy = y; 90 91 if (n->getStatus() == STOP || n->getStatus() == UNSTOP) 92 myy += (nodeWidth-failedWidth)/2; 93 94 if (n != startNode()) { 95 if (n->isOnPath()) 96 painter.setPen(Qt::red); 97 else 98 painter.setPen(Qt::black); 99 // Here we use drawPath instead of drawLine in order to 100 // workaround a strange redraw artefact on Windows 101 QPainterPath path; 102 path.moveTo(myx,myy); 103 path.lineTo(parentX,parentY); 104 painter.drawPath(path); 105 106 QFontMetrics fm = painter.fontMetrics(); 107 QString label = na.getLabel(n); 108 int alt = n->getAlternative(na); 109 int n_alt = n->getParent(na)->getNumberOfChildren(); 110 int tw = fm.width(label); 111 int lx; 112 if (alt==0 && n_alt > 1) { 113 lx = myx-tw-4; 114 } else if (alt==n_alt-1 && n_alt > 1) { 115 lx = myx+4; 116 } else { 117 lx = myx-tw/2; 118 } 119 painter.drawText(QPointF(lx,myy-2),label); 120 } 121 122 // draw shadow 123 if (n->isMarked()) { 124 painter.setBrush(Qt::gray); 125 painter.setPen(Qt::NoPen); 126 if (n->isHidden()) { 127 QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset), 128 QPointF(myx+nodeWidth+shadowOffset, 129 myy+hiddenDepth+shadowOffset), 130 QPointF(myx-nodeWidth+shadowOffset, 131 myy+hiddenDepth+shadowOffset), 132 }; 133 painter.drawConvexPolygon(points, 3); 134 135 } else { 136 switch (n->getStatus()) { 137 case Gist::SOLVED: 138 { 139 QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset), 140 QPointF(myx+halfNodeWidth+shadowOffset, 141 myy+halfNodeWidth+shadowOffset), 142 QPointF(myx+shadowOffset, 143 myy+nodeWidth+shadowOffset), 144 QPointF(myx-halfNodeWidth+shadowOffset, 145 myy+halfNodeWidth+shadowOffset) 146 }; 147 painter.drawConvexPolygon(points, 4); 148 } 149 break; 150 case Gist::FAILED: 151 painter.drawRect(myx-halfFailedWidth+shadowOffset, 152 myy+shadowOffset, failedWidth, failedWidth); 153 break; 154 case Gist::UNSTOP: 155 case Gist::STOP: 156 { 157 QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF, 158 myy+shadowOffset), 159 QPointF(myx+shadowOffset+quarterFailedWidthF, 160 myy+shadowOffset), 161 QPointF(myx+shadowOffset+halfFailedWidth, 162 myy+shadowOffset 163 +quarterFailedWidthF), 164 QPointF(myx+shadowOffset+halfFailedWidth, 165 myy+shadowOffset+halfFailedWidth+ 166 quarterFailedWidthF), 167 QPointF(myx+shadowOffset+quarterFailedWidthF, 168 myy+shadowOffset+failedWidth), 169 QPointF(myx+shadowOffset-quarterFailedWidthF, 170 myy+shadowOffset+failedWidth), 171 QPointF(myx+shadowOffset-halfFailedWidth, 172 myy+shadowOffset+halfFailedWidth+ 173 quarterFailedWidthF), 174 QPointF(myx+shadowOffset-halfFailedWidth, 175 myy+shadowOffset 176 +quarterFailedWidthF), 177 }; 178 painter.drawConvexPolygon(points, 8); 179 } 180 break; 181 case Gist::BRANCH: 182 painter.drawEllipse(myx-halfNodeWidth+shadowOffset, 183 myy+shadowOffset, nodeWidth, nodeWidth); 184 break; 185 case Gist::UNDETERMINED: 186 painter.drawEllipse(myx-halfNodeWidth+shadowOffset, 187 myy+shadowOffset, nodeWidth, nodeWidth); 188 break; 189 } 190 } 191 } 192 193 painter.setPen(Qt::SolidLine); 194 if (n->isHidden()) { 195 if (n->hasOpenChildren()) { 196 QLinearGradient gradient(myx-nodeWidth,myy, 197 myx+nodeWidth*1.3,myy+hiddenDepth*1.3); 198 if (n->hasSolvedChildren()) { 199 gradient.setColorAt(0, white); 200 gradient.setColorAt(1, green); 201 } else if (n->hasFailedChildren()) { 202 gradient.setColorAt(0, white); 203 gradient.setColorAt(1, red); 204 } else { 205 gradient.setColorAt(0, white); 206 gradient.setColorAt(1, QColor(0,0,0)); 207 } 208 painter.setBrush(gradient); 209 } else { 210 if (n->hasSolvedChildren()) 211 painter.setBrush(QBrush(green)); 212 else 213 painter.setBrush(QBrush(red)); 214 } 215 216 QPointF points[3] = {QPointF(myx,myy), 217 QPointF(myx+nodeWidth,myy+hiddenDepth), 218 QPointF(myx-nodeWidth,myy+hiddenDepth), 219 }; 220 painter.drawConvexPolygon(points, 3); 221 } else { 222 switch (n->getStatus()) { 223 case Gist::SOLVED: 224 { 225 if (n->isCurrentBest(curBest)) { 226 painter.setBrush(QBrush(orange)); 227 } else { 228 painter.setBrush(QBrush(green)); 229 } 230 QPointF points[4] = {QPointF(myx,myy), 231 QPointF(myx+halfNodeWidth,myy+halfNodeWidth), 232 QPointF(myx,myy+nodeWidth), 233 QPointF(myx-halfNodeWidth,myy+halfNodeWidth) 234 }; 235 painter.drawConvexPolygon(points, 4); 236 } 237 break; 238 case Gist::FAILED: 239 painter.setBrush(QBrush(red)); 240 painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth); 241 break; 242 case Gist::UNSTOP: 243 case Gist::STOP: 244 { 245 painter.setBrush(n->getStatus() == STOP ? 246 QBrush(red) : QBrush(green)); 247 QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy), 248 QPointF(myx+quarterFailedWidthF,myy), 249 QPointF(myx+halfFailedWidth, 250 myy+quarterFailedWidthF), 251 QPointF(myx+halfFailedWidth, 252 myy+halfFailedWidth+ 253 quarterFailedWidthF), 254 QPointF(myx+quarterFailedWidthF, 255 myy+failedWidth), 256 QPointF(myx-quarterFailedWidthF, 257 myy+failedWidth), 258 QPointF(myx-halfFailedWidth, 259 myy+halfFailedWidth+ 260 quarterFailedWidthF), 261 QPointF(myx-halfFailedWidth, 262 myy+quarterFailedWidthF), 263 }; 264 painter.drawConvexPolygon(points, 8); 265 } 266 break; 267 case Gist::BRANCH: 268 painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) : 269 QBrush(white)); 270 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth); 271 break; 272 case Gist::UNDETERMINED: 273 painter.setBrush(Qt::white); 274 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth); 275 break; 276 } 277 } 278 279 if (copies && (n->hasCopy() && !n->hasWorkingSpace())) { 280 painter.setBrush(Qt::darkRed); 281 painter.drawEllipse(myx, myy, 10.0, 10.0); 282 } 283 284 if (copies && n->hasWorkingSpace()) { 285 painter.setBrush(Qt::darkYellow); 286 painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0); 287 } 288 289 if (n->isBookmarked()) { 290 painter.setBrush(Qt::black); 291 painter.drawEllipse(myx-10-0, myy, 10.0, 10.0); 292 } 293 294 } 295 296}} 297 298// STATISTICS: gist-any