Generated on for Gecode by doxygen 1.15.0
drawingcursor.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Guido Tack <tack@gecode.dev>
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.dev
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
35
36namespace Gecode { namespace Gist {
37
39 const QColor DrawingCursor::red(218, 37, 29);
41 const QColor DrawingCursor::green(11, 118, 70);
43 const QColor DrawingCursor::blue(0, 92, 161);
45 const QColor DrawingCursor::orange(235, 137, 27);
47 const QColor DrawingCursor::white(255,255,255);
48
50 const QColor DrawingCursor::lightRed(218, 37, 29, 120);
52 const QColor DrawingCursor::lightGreen(11, 118, 70, 120);
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
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
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#if QT_VERSION >= 0x060000
111 int tw = fm.horizontalAdvance(label);
112#else
113 int tw = fm.width(label);
114#endif
115 int lx;
116 if (alt==0 && n_alt > 1) {
117 lx = myx-tw-4;
118 } else if (alt==n_alt-1 && n_alt > 1) {
119 lx = myx+4;
120 } else {
121 lx = myx-tw/2;
122 }
123 painter.drawText(QPointF(lx,myy-2),label);
124 }
125
126 // draw shadow
127 if (n->isMarked()) {
128 painter.setBrush(Qt::gray);
129 painter.setPen(Qt::NoPen);
130 if (n->isHidden()) {
131 QPointF points[3] = {QPointF(myx+shadowOffset,myy+shadowOffset),
132 QPointF(myx+nodeWidth+shadowOffset,
134 QPointF(myx-nodeWidth+shadowOffset,
136 };
137 painter.drawConvexPolygon(points, 3);
138
139 } else {
140 switch (n->getStatus()) {
141 case Gist::SOLVED:
142 {
143 QPointF points[4] = {QPointF(myx+shadowOffset,myy+shadowOffset),
144 QPointF(myx+halfNodeWidth+shadowOffset,
146 QPointF(myx+shadowOffset,
148 QPointF(myx-halfNodeWidth+shadowOffset,
150 };
151 painter.drawConvexPolygon(points, 4);
152 }
153 break;
154 case Gist::FAILED:
155 painter.drawRect(myx-halfFailedWidth+shadowOffset,
157 break;
158 case Gist::UNSTOP:
159 case Gist::STOP:
160 {
161 QPointF points[8] = {QPointF(myx+shadowOffset-quarterFailedWidthF,
162 myy+shadowOffset),
164 myy+shadowOffset),
165 QPointF(myx+shadowOffset+halfFailedWidth,
166 myy+shadowOffset
168 QPointF(myx+shadowOffset+halfFailedWidth,
175 QPointF(myx+shadowOffset-halfFailedWidth,
178 QPointF(myx+shadowOffset-halfFailedWidth,
179 myy+shadowOffset
181 };
182 painter.drawConvexPolygon(points, 8);
183 }
184 break;
185 case Gist::BRANCH:
186 painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
188 break;
190 painter.drawEllipse(myx-halfNodeWidth+shadowOffset,
192 break;
193 }
194 }
195 }
196
197 painter.setPen(Qt::SolidLine);
198 if (n->isHidden()) {
199 if (n->hasOpenChildren()) {
200 QLinearGradient gradient(myx-nodeWidth,myy,
201 myx+nodeWidth*1.3,myy+hiddenDepth*1.3);
202 if (n->hasSolvedChildren()) {
203 gradient.setColorAt(0, white);
204 gradient.setColorAt(1, green);
205 } else if (n->hasFailedChildren()) {
206 gradient.setColorAt(0, white);
207 gradient.setColorAt(1, red);
208 } else {
209 gradient.setColorAt(0, white);
210 gradient.setColorAt(1, QColor(0,0,0));
211 }
212 painter.setBrush(gradient);
213 } else {
214 if (n->hasSolvedChildren())
215 painter.setBrush(QBrush(green));
216 else
217 painter.setBrush(QBrush(red));
218 }
219
220 QPointF points[3] = {QPointF(myx,myy),
221 QPointF(myx+nodeWidth,myy+hiddenDepth),
222 QPointF(myx-nodeWidth,myy+hiddenDepth),
223 };
224 painter.drawConvexPolygon(points, 3);
225 } else {
226 switch (n->getStatus()) {
227 case Gist::SOLVED:
228 {
229 if (n->isCurrentBest(curBest)) {
230 painter.setBrush(QBrush(orange));
231 } else {
232 painter.setBrush(QBrush(green));
233 }
234 QPointF points[4] = {QPointF(myx,myy),
235 QPointF(myx+halfNodeWidth,myy+halfNodeWidth),
236 QPointF(myx,myy+nodeWidth),
237 QPointF(myx-halfNodeWidth,myy+halfNodeWidth)
238 };
239 painter.drawConvexPolygon(points, 4);
240 }
241 break;
242 case Gist::FAILED:
243 painter.setBrush(QBrush(red));
244 painter.drawRect(myx-halfFailedWidth, myy, failedWidth, failedWidth);
245 break;
246 case Gist::UNSTOP:
247 case Gist::STOP:
248 {
249 painter.setBrush(n->getStatus() == STOP ?
250 QBrush(red) : QBrush(green));
251 QPointF points[8] = {QPointF(myx-quarterFailedWidthF,myy),
252 QPointF(myx+quarterFailedWidthF,myy),
253 QPointF(myx+halfFailedWidth,
255 QPointF(myx+halfFailedWidth,
256 myy+halfFailedWidth+
258 QPointF(myx+quarterFailedWidthF,
259 myy+failedWidth),
260 QPointF(myx-quarterFailedWidthF,
261 myy+failedWidth),
262 QPointF(myx-halfFailedWidth,
263 myy+halfFailedWidth+
265 QPointF(myx-halfFailedWidth,
267 };
268 painter.drawConvexPolygon(points, 8);
269 }
270 break;
271 case Gist::BRANCH:
272 painter.setBrush(n->childrenLayoutIsDone() ? QBrush(blue) :
273 QBrush(white));
274 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
275 break;
277 painter.setBrush(Qt::white);
278 painter.drawEllipse(myx-halfNodeWidth, myy, nodeWidth, nodeWidth);
279 break;
280 }
281 }
282
283 if (copies && (n->hasCopy() && !n->hasWorkingSpace())) {
284 painter.setBrush(Qt::darkRed);
285 painter.drawEllipse(myx, myy, 10.0, 10.0);
286 }
287
288 if (copies && n->hasWorkingSpace()) {
289 painter.setBrush(Qt::darkYellow);
290 painter.drawEllipse(myx, myy + 10.0, 10.0, 10.0);
291 }
292
293 if (n->isBookmarked()) {
294 painter.setBrush(Qt::black);
295 painter.drawEllipse(myx-10-0, myy, 10.0, 10.0);
296 }
297
298 }
299
300}}
301
302// STATISTICS: gist-any
Static reference to the currently best space.
Definition spacenode.hh:80
static const QColor red
The color for failed nodes.
void processCurrentNode(void)
Draw the node.
static const QColor blue
The color for choice nodes.
static const QColor green
The color for solved nodes.
static const QColor white
White color.
static const QColor lightBlue
The color for expanded choice nodes.
DrawingCursor(VisualNode *root, const VisualNode::NodeAllocator &na, BestNode *curBest0, QPainter &painter0, const QRect &clippingRect0, bool showCopies)
Constructor.
static const QColor lightRed
The color for expanded failed nodes.
static const QColor lightGreen
The color for expanded solved nodes.
static const QColor orange
The color for the best solution.
static const int dist_y
Definition visualnode.hh:46
const VisualNode::NodeAllocator & na
Definition nodecursor.hh:53
NodeCursor(VisualNode *theNode, const typename VisualNode::NodeAllocator &na)
NodeAllocatorBase< VisualNode > NodeAllocator
Definition node.hh:143
int getParent(void) const
Return the parent.
Definition node.hpp:182
bool isRoot(void) const
Check if this node is the root of a tree.
Definition node.hpp:211
bool hasCopy(void)
Return whether the node has a copy.
bool hasWorkingSpace(void)
Return whether the node has a working space.
bool isCurrentBest(BestNode *curBest)
Return whether this node is the currently best solution.
bool hasFailedChildren(void)
Return whether the subtree of this node has any failed children.
bool hasSolvedChildren(void)
Return whether the subtree of this node has any solved children.
int getAlternative(const NodeAllocator &na) const
Return alternative number of this node.
NodeStatus getStatus(void) const
Return current status of the node.
Definition spacenode.hpp:71
bool hasOpenChildren(void)
Return whether the subtree of this node has any open children.
Node class that supports visual layout
int getOffset(void)
Return offset off this node from its parent.
bool isBookmarked(void)
Return whether node is bookmarked.
bool isHidden(void)
Return if node is hidden.
bool isMarked(void)
Return whether node is marked.
bool childrenLayoutIsDone(void)
Return whether the layout of the node's children has been completed.
bool isOnPath(void)
Return whether node is on the path.
The Gecode Interactive Search Tool.
const double shadowOffset
const double failedWidth
const double halfNodeWidth
@ UNDETERMINED
Node that has not been explored yet.
Definition spacenode.hh:48
@ UNSTOP
Node representing ignored stop point.
Definition spacenode.hh:50
@ FAILED
Node representing failure.
Definition spacenode.hh:46
@ STOP
Node representing stop point.
Definition spacenode.hh:49
@ SOLVED
Node representing a solution.
Definition spacenode.hh:45
@ BRANCH
Node representing a branch.
Definition spacenode.hh:47
const double hiddenDepth
const double nodeWidth
const double halfFailedWidth
const double quarterFailedWidthF
Gecode toplevel namespace
void path(Home home, const IntVarArgs &x, IntVar s, IntVar e, IntPropLevel ipl=IPL_DEF)
Post propagator such that x forms a Hamiltonian path.
Definition circuit.cpp:169