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