00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <gecode/gist/visualnode.hh>
00039
00040 #include <gecode/gist/layoutcursor.hh>
00041 #include <gecode/gist/nodevisitor.hh>
00042
00043 #include <utility>
00044
00045 namespace Gecode { namespace Gist {
00046
00047 Shape* Shape::leaf;
00048 Shape* Shape::hidden;
00049
00051 class ShapeAllocator {
00052 public:
00054 ShapeAllocator(void) {
00055 Shape::leaf = Shape::allocate(1);
00056 (*Shape::leaf)[0] = Extent(Layout::extent);
00057 Shape::leaf->computeBoundingBox();
00058
00059 Shape::hidden = Shape::allocate(2);
00060 (*Shape::hidden)[0] = Extent(Layout::extent);
00061 (*Shape::hidden)[1] = Extent(Layout::extent);
00062 Shape::hidden->computeBoundingBox();
00063 }
00064 ~ShapeAllocator(void) {
00065 Shape::deallocate(Shape::leaf);
00066 Shape::deallocate(Shape::hidden);
00067 }
00068 };
00069
00071 ShapeAllocator shapeAllocator;
00072
00073 VisualNode::VisualNode(int p)
00074 : SpaceNode(p)
00075 , offset(0)
00076 {
00077 shape = NULL;
00078 setDirty(true);
00079 setChildrenLayoutDone(false);
00080 setHidden(false);
00081 setMarked(false);
00082 setOnPath(false);
00083 setBookmarked(false);
00084 }
00085
00086 VisualNode::VisualNode(Space* root)
00087 : SpaceNode(root)
00088 , offset(0)
00089 {
00090 shape = NULL;
00091 setDirty(true);
00092 setChildrenLayoutDone(false);
00093 setHidden(false);
00094 setMarked(false);
00095 setOnPath(false);
00096 setBookmarked(false);
00097 }
00098
00099 void
00100 VisualNode::dispose(void) {
00101 Shape::deallocate(shape);
00102 SpaceNode::dispose();
00103 }
00104
00105 void
00106 VisualNode::dirtyUp(const NodeAllocator& na) {
00107 VisualNode* cur = this;
00108 while (!cur->isDirty()) {
00109 cur->setDirty(true);
00110 if (! cur->isRoot()) {
00111 cur = cur->getParent(na);
00112 }
00113 }
00114 }
00115
00116 void
00117 VisualNode::layout(const NodeAllocator& na) {
00118 LayoutCursor l(this,na);
00119 PostorderNodeVisitor<LayoutCursor>(l).run();
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 }
00130
00131 void VisualNode::pathUp(const NodeAllocator& na) {
00132 VisualNode* cur = this;
00133 while (cur) {
00134 cur->setOnPath(true);
00135 cur = cur->getParent(na);
00136 }
00137 }
00138
00139 void VisualNode::unPathUp(const NodeAllocator& na) {
00140 VisualNode* cur = this;
00141 while (!cur->isRoot()) {
00142 cur->setOnPath(false);
00143 cur = cur->getParent(na);
00144 }
00145 }
00146
00147 int
00148 VisualNode::getPathAlternative(const NodeAllocator& na) {
00149 for (int i=getNumberOfChildren(); i--;) {
00150 if (getChild(na,i)->isOnPath())
00151 return i;
00152 }
00153 return -1;
00154 }
00155
00156 void
00157 VisualNode::toggleHidden(const NodeAllocator& na) {
00158 setHidden(!isHidden());
00159 dirtyUp(na);
00160 }
00161
00162 void
00163 VisualNode::hideFailed(const NodeAllocator& na, bool onlyDirty) {
00164 HideFailedCursor c(this,na,onlyDirty);
00165 PreorderNodeVisitor<HideFailedCursor>(c).run();
00166 dirtyUp(na);
00167 }
00168
00169 void
00170 VisualNode::labelBranches(NodeAllocator& na,
00171 BestNode* curBest, int c_d, int a_d) {
00172 bool clear = na.hasLabel(this);
00173 BranchLabelCursor c(this,curBest,c_d,a_d,clear,na);
00174 PreorderNodeVisitor<BranchLabelCursor>(c).run();
00175 dirtyUp(na);
00176 }
00177
00178 void
00179 VisualNode::labelPath(NodeAllocator& na,
00180 BestNode* curBest, int c_d, int a_d) {
00181 if (na.hasLabel(this)) {
00182
00183 VisualNode* p = this;
00184 while (p) {
00185 na.clearLabel(p);
00186 p = p->getParent(na);
00187 }
00188 } else {
00189
00190 std::vector<std::pair<VisualNode*,int> > path;
00191 VisualNode* p = this;
00192 while (p) {
00193 path.push_back(std::pair<VisualNode*,int>(p,p->getAlternative(na)));
00194 p = p->getParent(na);
00195 }
00196 while (!path.empty()) {
00197 std::pair<VisualNode*,int> cur = path.back(); path.pop_back();
00198 if (p) {
00199 std::string l =
00200 cur.first->getBranchLabel(na,p,p->getChoice(),
00201 curBest,c_d,a_d,cur.second);
00202 na.setLabel(cur.first,QString(l.c_str()));
00203 }
00204 p = cur.first;
00205 }
00206 }
00207 dirtyUp(na);
00208 }
00209
00210 void
00211 VisualNode::unhideAll(const NodeAllocator& na) {
00212 UnhideAllCursor c(this,na);
00213 PreorderNodeVisitor<UnhideAllCursor>(c).run();
00214 dirtyUp(na);
00215 }
00216
00217 void
00218 VisualNode::toggleStop(const NodeAllocator& na) {
00219 if (getStatus() == STOP)
00220 setStatus(UNSTOP);
00221 else if (getStatus() == UNSTOP)
00222 setStatus(STOP);
00223 dirtyUp(na);
00224 }
00225
00226 void
00227 VisualNode::unstopAll(const NodeAllocator& na) {
00228 UnstopAllCursor c(this,na);
00229 PreorderNodeVisitor<UnstopAllCursor>(c).run();
00230 dirtyUp(na);
00231 }
00232
00233 void
00234 VisualNode::changedStatus(const NodeAllocator& na) { dirtyUp(na); }
00235
00236 bool
00237 VisualNode::containsCoordinateAtDepth(int x, int depth) {
00238 BoundingBox box = getShape()->getBoundingBox();
00239 if (x < box.left ||
00240 x > box.right ||
00241 depth >= getShape()->depth()) {
00242 return false;
00243 }
00244 Extent theExtent;
00245 if (getShape()->getExtentAtDepth(depth, theExtent)) {
00246 return (theExtent.l <= x && x <= theExtent.r);
00247 } else {
00248 return false;
00249 }
00250 }
00251
00252 VisualNode*
00253 VisualNode::findNode(const NodeAllocator& na, int x, int y) {
00254 VisualNode* cur = this;
00255 int depth = y / Layout::dist_y;
00256
00257 while (depth > 0 && cur != NULL) {
00258 if (cur->isHidden()) {
00259 break;
00260 }
00261 VisualNode* oldCur = cur;
00262 cur = NULL;
00263 for (unsigned int i=0; i<oldCur->getNumberOfChildren(); i++) {
00264 VisualNode* nextChild = oldCur->getChild(na,i);
00265 int newX = x - nextChild->getOffset();
00266 if (nextChild->containsCoordinateAtDepth(newX, depth - 1)) {
00267 cur = nextChild;
00268 x = newX;
00269 break;
00270 }
00271 }
00272 depth--;
00273 y -= Layout::dist_y;
00274 }
00275
00276 if(cur == this && !cur->containsCoordinateAtDepth(x, 0)) {
00277 return NULL;
00278 }
00279 return cur;
00280 }
00281
00282 std::string
00283 VisualNode::toolTip(NodeAllocator&, BestNode*, int, int) {
00284 return "";
00285 }
00286
00287 std::string
00288 VisualNode::getBranchLabel(NodeAllocator& na,
00289 VisualNode* p, const Choice* c,
00290 BestNode* curBest, int c_d, int a_d, int alt) {
00291 std::ostringstream oss;
00292 p->acquireSpace(na,curBest,c_d,a_d);
00293 p->getWorkingSpace()->print(*c,alt,oss);
00294 return oss.str();
00295 }
00296
00297
00299 class Layouter {
00300 public:
00302 template<class S1, class S2>
00303 static int getAlpha(const S1& shape1, int depth1,
00304 const S2& shape2, int depth2);
00306 template<class S1, class S2>
00307 static void merge(Extent* result,
00308 const S1& shape1, int depth1,
00309 const S2& shape2, int depth2, int alpha);
00310 };
00311
00312 template<class S1, class S2>
00313 int
00314 Layouter::getAlpha(const S1& shape1, int depth1,
00315 const S2& shape2, int depth2) {
00316 int alpha = Layout::minimalSeparation;
00317 int extentR = 0;
00318 int extentL = 0;
00319 for (int i=0; i<depth1 && i<depth2; i++) {
00320 extentR += shape1[i].r;
00321 extentL += shape2[i].l;
00322 alpha = std::max(alpha, extentR - extentL + Layout::minimalSeparation);
00323 }
00324 return alpha;
00325 }
00326
00327 template<class S1, class S2>
00328 void
00329 Layouter::merge(Extent* result,
00330 const S1& shape1, int depth1,
00331 const S2& shape2, int depth2, int alpha) {
00332 if (depth1 == 0) {
00333 for (int i=depth2; i--;)
00334 result[i] = shape2[i];
00335 } else if (depth2 == 0) {
00336 for (int i=depth1; i--;)
00337 result[i] = shape1[i];
00338 } else {
00339
00340
00341 int topmostL = shape1[0].l;
00342 int topmostR = shape2[0].r;
00343 int backoffTo1 =
00344 shape1[0].r - alpha - shape2[0].r;
00345 int backoffTo2 =
00346 shape2[0].l + alpha - shape1[0].l;
00347
00348 result[0] = Extent(topmostL, topmostR+alpha);
00349
00350
00351
00352
00353
00354
00355 int i=1;
00356 for (; i<depth1 && i<depth2; i++) {
00357 Extent currentExtent1 = shape1[i];
00358 Extent currentExtent2 = shape2[i];
00359 int newExtentL = currentExtent1.l;
00360 int newExtentR = currentExtent2.r;
00361 result[i] = Extent(newExtentL, newExtentR);
00362 backoffTo1 += currentExtent1.r - currentExtent2.r;
00363 backoffTo2 += currentExtent2.l - currentExtent1.l;
00364 }
00365
00366
00367
00368 if (i<depth1) {
00369 Extent currentExtent1 = shape1[i];
00370 int newExtentL = currentExtent1.l;
00371 int newExtentR = currentExtent1.r;
00372 result[i] = Extent(newExtentL, newExtentR+backoffTo1);
00373 ++i;
00374 for (; i<depth1; i++) {
00375 result[i] = shape1[i];
00376 }
00377 }
00378
00379
00380
00381 if (i<depth2) {
00382 Extent currentExtent2 = shape2[i];
00383 int newExtentL = currentExtent2.l;
00384 int newExtentR = currentExtent2.r;
00385 result[i] = Extent(newExtentL+backoffTo2, newExtentR);
00386 ++i;
00387 for (; i<depth2; i++) {
00388 result[i] = shape2[i];
00389 }
00390 }
00391 }
00392 }
00393
00394 void
00395 VisualNode::setShape(Shape* s) {
00396 if (shape != s)
00397 Shape::deallocate(shape);
00398 shape = s;
00399 shape->computeBoundingBox();
00400 }
00401
00402 void
00403 VisualNode::computeShape(const NodeAllocator& na, VisualNode* root) {
00404 int numberOfShapes = getNumberOfChildren();
00405 Extent extent;
00406 if (na.hasLabel(this)) {
00407 int ll = na.getLabel(this).length();
00408 ll *= 7;
00409 VisualNode* p = getParent(na);
00410 int alt = 0;
00411 int n_alt = 1;
00412 if (p) {
00413 alt = getAlternative(na);
00414 n_alt = p->getNumberOfChildren();
00415 }
00416 extent = Extent(Layout::extent);
00417 if (alt==0 && n_alt > 1) {
00418 extent.l = std::min(extent.l, -ll);
00419 } else if (alt==n_alt-1 && n_alt > 1) {
00420 extent.r = std::max(extent.r, ll);
00421 } else {
00422 extent.l = std::min(extent.l, -ll);
00423 extent.r = std::max(extent.r, ll);
00424 }
00425 } else {
00426 if (numberOfShapes==0) {
00427 setShape(Shape::leaf);
00428 return;
00429 } else {
00430 extent = Extent(Layout::extent);
00431 }
00432 }
00433
00434 int maxDepth = 0;
00435 for (int i = numberOfShapes; i--;)
00436 maxDepth = std::max(maxDepth, getChild(na,i)->getShape()->depth());
00437 Shape* mergedShape;
00438 if (getShape() && getShape() != Shape::leaf &&
00439 getShape()->depth() >= maxDepth+1) {
00440 mergedShape = getShape();
00441 mergedShape->setDepth(maxDepth+1);
00442 } else {
00443 mergedShape = Shape::allocate(maxDepth+1);
00444 }
00445 (*mergedShape)[0] = extent;
00446 if (numberOfShapes < 1) {
00447 setShape(mergedShape);
00448 } else if (numberOfShapes == 1) {
00449 getChild(na,0)->setOffset(0);
00450 const Shape* childShape = getChild(na,0)->getShape();
00451 for (int i=childShape->depth(); i--;)
00452 (*mergedShape)[i+1] = (*childShape)[i];
00453 (*mergedShape)[1].extend(- extent.l, - extent.r);
00454 setShape(mergedShape);
00455 } else {
00456
00457
00458
00459
00460
00461
00462 assert(root->copy != NULL);
00463 Region r(*root->copy);
00464 std::pair<int,int>* alpha =
00465 r.alloc<std::pair<int,int> >(numberOfShapes);
00466
00467
00468 int width = 0;
00469
00470 Extent* currentShapeL = r.alloc<Extent>(maxDepth);
00471 int ldepth = getChild(na,0)->getShape()->depth();
00472 for (int i=ldepth; i--;)
00473 currentShapeL[i] = (*getChild(na,0)->getShape())[i];
00474
00475
00476
00477 Shape* rShape = getChild(na,numberOfShapes-1)->getShape();
00478 int rdepth = rShape->depth();
00479 for (int i=rdepth; i--;)
00480 (*mergedShape)[i+1] = (*rShape)[i];
00481 Extent* currentShapeR = &(*mergedShape)[1];
00482
00483 for (int i = 1; i < numberOfShapes; i++) {
00484
00485
00486
00487
00488
00489
00490
00491 Shape* nextShapeL = getChild(na,i)->getShape();
00492 int nextAlphaL =
00493 Layouter::getAlpha<Extent*,Shape>(¤tShapeL[0], ldepth,
00494 *nextShapeL, nextShapeL->depth());
00495 Layouter::merge<Extent*,Shape>(¤tShapeL[0],
00496 ¤tShapeL[0], ldepth,
00497 *nextShapeL, nextShapeL->depth(),
00498 nextAlphaL);
00499 ldepth = std::max(ldepth,nextShapeL->depth());
00500 alpha[i].first = nextAlphaL - width;
00501 width = nextAlphaL;
00502
00503
00504
00505 Shape* nextShapeR = getChild(na,numberOfShapes-1-i)->getShape();
00506 int nextAlphaR =
00507 Layouter::getAlpha<Shape,Extent*>(*nextShapeR, nextShapeR->depth(),
00508 ¤tShapeR[0], rdepth);
00509 Layouter::merge<Shape,Extent*>(¤tShapeR[0],
00510 *nextShapeR, nextShapeR->depth(),
00511 ¤tShapeR[0], rdepth,
00512 nextAlphaR);
00513 rdepth = std::max(rdepth,nextShapeR->depth());
00514 alpha[numberOfShapes - i].second = nextAlphaR;
00515 }
00516
00517
00518 (*mergedShape)[1].extend(- extent.l, - extent.r);
00519
00520
00521
00522
00523
00524 int halfWidth = false ? 0 : width / 2;
00525 (*mergedShape)[1].move(- halfWidth);
00526
00527
00528
00529
00530
00531
00532
00533 int offset = - halfWidth;
00534 getChild(na,0)->setOffset(offset);
00535 for (int i = 1; i < numberOfShapes; i++) {
00536 offset += (alpha[i].first + alpha[i].second) / 2;
00537 getChild(na,i)->setOffset(offset);
00538 }
00539 setShape(mergedShape);
00540 }
00541 }
00542
00543 }}
00544
00545