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::hidden = Shape::allocate(2);
00057 (*Shape::hidden)[1] = Extent(Layout::extent);
00058 Shape::leaf->computeBoundingBox();
00059 Shape::hidden->computeBoundingBox();
00060 }
00061 ~ShapeAllocator(void) {
00062 Shape::deallocate(Shape::leaf);
00063 Shape::deallocate(Shape::hidden);
00064 }
00065 };
00066
00068 ShapeAllocator shapeAllocator;
00069
00070 VisualNode::VisualNode(int p)
00071 : SpaceNode(p)
00072 , offset(0)
00073 {
00074 shape = NULL;
00075 setDirty(true);
00076 setChildrenLayoutDone(false);
00077 setHidden(false);
00078 setMarked(false);
00079 setOnPath(false);
00080 setBookmarked(false);
00081 }
00082
00083 VisualNode::VisualNode(Space* root)
00084 : SpaceNode(root)
00085 , offset(0)
00086 {
00087 shape = NULL;
00088 setDirty(true);
00089 setChildrenLayoutDone(false);
00090 setHidden(false);
00091 setMarked(false);
00092 setOnPath(false);
00093 setBookmarked(false);
00094 }
00095
00096 void
00097 VisualNode::dispose(void) {
00098 Shape::deallocate(shape);
00099 SpaceNode::dispose();
00100 }
00101
00102 void
00103 VisualNode::dirtyUp(const NodeAllocator& na) {
00104 VisualNode* cur = this;
00105 while (!cur->isDirty()) {
00106 cur->setDirty(true);
00107 if (! cur->isRoot()) {
00108 cur = cur->getParent(na);
00109 }
00110 }
00111 }
00112
00113 void
00114 VisualNode::layout(const NodeAllocator& na) {
00115 LayoutCursor l(this,na);
00116 PostorderNodeVisitor<LayoutCursor>(l).run();
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 }
00127
00128 void VisualNode::pathUp(const NodeAllocator& na) {
00129 VisualNode* cur = this;
00130 while (cur) {
00131 cur->setOnPath(true);
00132 cur = cur->getParent(na);
00133 }
00134 }
00135
00136 void VisualNode::unPathUp(const NodeAllocator& na) {
00137 VisualNode* cur = this;
00138 while (!cur->isRoot()) {
00139 cur->setOnPath(false);
00140 cur = cur->getParent(na);
00141 }
00142 }
00143
00144 int
00145 VisualNode::getPathAlternative(const NodeAllocator& na) {
00146 for (int i=getNumberOfChildren(); i--;) {
00147 if (getChild(na,i)->isOnPath())
00148 return i;
00149 }
00150 return -1;
00151 }
00152
00153 void
00154 VisualNode::toggleHidden(const NodeAllocator& na) {
00155 setHidden(!isHidden());
00156 dirtyUp(na);
00157 }
00158
00159 void
00160 VisualNode::hideFailed(const NodeAllocator& na, bool onlyDirty) {
00161 HideFailedCursor c(this,na,onlyDirty);
00162 PreorderNodeVisitor<HideFailedCursor>(c).run();
00163 dirtyUp(na);
00164 }
00165
00166 void
00167 VisualNode::unhideAll(const NodeAllocator& na) {
00168 UnhideAllCursor c(this,na);
00169 PreorderNodeVisitor<UnhideAllCursor>(c).run();
00170 dirtyUp(na);
00171 }
00172
00173 void
00174 VisualNode::toggleStop(const NodeAllocator& na) {
00175 if (getStatus() == STOP)
00176 setStatus(UNSTOP);
00177 else if (getStatus() == UNSTOP)
00178 setStatus(STOP);
00179 dirtyUp(na);
00180 }
00181
00182 void
00183 VisualNode::unstopAll(const NodeAllocator& na) {
00184 UnstopAllCursor c(this,na);
00185 PreorderNodeVisitor<UnstopAllCursor>(c).run();
00186 dirtyUp(na);
00187 }
00188
00189 void
00190 VisualNode::changedStatus(const NodeAllocator& na) { dirtyUp(na); }
00191
00192 bool
00193 VisualNode::containsCoordinateAtDepth(int x, int depth) {
00194 BoundingBox box = getShape()->getBoundingBox();
00195 if (x < box.left ||
00196 x > box.right ||
00197 depth >= getShape()->depth()) {
00198 return false;
00199 }
00200 Extent theExtent;
00201 if (getShape()->getExtentAtDepth(depth, theExtent)) {
00202 return (theExtent.l <= x && x <= theExtent.r);
00203 } else {
00204 return false;
00205 }
00206 }
00207
00208 VisualNode*
00209 VisualNode::findNode(const NodeAllocator& na, int x, int y) {
00210 VisualNode* cur = this;
00211 int depth = y / Layout::dist_y;
00212
00213 while (depth > 0 && cur != NULL) {
00214 if (cur->isHidden()) {
00215 break;
00216 }
00217 VisualNode* oldCur = cur;
00218 cur = NULL;
00219 for (unsigned int i=0; i<oldCur->getNumberOfChildren(); i++) {
00220 VisualNode* nextChild = oldCur->getChild(na,i);
00221 int newX = x - nextChild->getOffset();
00222 if (nextChild->containsCoordinateAtDepth(newX, depth - 1)) {
00223 cur = nextChild;
00224 x = newX;
00225 break;
00226 }
00227 }
00228 depth--;
00229 y -= Layout::dist_y;
00230 }
00231
00232 if(cur == this && !cur->containsCoordinateAtDepth(x, 0)) {
00233 return NULL;
00234 }
00235 return cur;
00236 }
00237
00238 std::string
00239 VisualNode::toolTip(BestNode*, int, int) {
00240 return "";
00241 }
00242
00244 class Layouter {
00245 public:
00247 template<class S1, class S2>
00248 static int getAlpha(const S1& shape1, int depth1,
00249 const S2& shape2, int depth2);
00251 template<class S1, class S2>
00252 static void merge(Extent* result,
00253 const S1& shape1, int depth1,
00254 const S2& shape2, int depth2, int alpha);
00255 };
00256
00257 template<class S1, class S2>
00258 int
00259 Layouter::getAlpha(const S1& shape1, int depth1,
00260 const S2& shape2, int depth2) {
00261 int alpha = Layout::minimalSeparation;
00262 int extentR = 0;
00263 int extentL = 0;
00264 for (int i=0; i<depth1 && i<depth2; i++) {
00265 extentR += shape1[i].r;
00266 extentL += shape2[i].l;
00267 alpha = std::max(alpha, extentR - extentL + Layout::minimalSeparation);
00268 }
00269 return alpha;
00270 }
00271
00272 template<class S1, class S2>
00273 void
00274 Layouter::merge(Extent* result,
00275 const S1& shape1, int depth1,
00276 const S2& shape2, int depth2, int alpha) {
00277 if (depth1 == 0) {
00278 for (int i=depth2; i--;)
00279 result[i] = shape2[i];
00280 } else if (depth2 == 0) {
00281 for (int i=depth1; i--;)
00282 result[i] = shape1[i];
00283 } else {
00284
00285
00286 int topmostL = shape1[0].l;
00287 int topmostR = shape2[0].r;
00288 int backoffTo1 =
00289 shape1[0].r - alpha - shape2[0].r;
00290 int backoffTo2 =
00291 shape2[0].l + alpha - shape1[0].l;
00292
00293 result[0] = Extent(topmostL, topmostR+alpha);
00294
00295
00296
00297
00298
00299
00300 int i=1;
00301 for (; i<depth1 && i<depth2; i++) {
00302 Extent currentExtent1 = shape1[i];
00303 Extent currentExtent2 = shape2[i];
00304 int newExtentL = currentExtent1.l;
00305 int newExtentR = currentExtent2.r;
00306 result[i] = Extent(newExtentL, newExtentR);
00307 backoffTo1 += currentExtent1.r - currentExtent2.r;
00308 backoffTo2 += currentExtent2.l - currentExtent1.l;
00309 }
00310
00311
00312
00313 if (i<depth1) {
00314 Extent currentExtent1 = shape1[i];
00315 int newExtentL = currentExtent1.l;
00316 int newExtentR = currentExtent1.r;
00317 result[i] = Extent(newExtentL, newExtentR+backoffTo1);
00318 ++i;
00319 for (; i<depth1; i++) {
00320 result[i] = shape1[i];
00321 }
00322 }
00323
00324
00325
00326 if (i<depth2) {
00327 Extent currentExtent2 = shape2[i];
00328 int newExtentL = currentExtent2.l;
00329 int newExtentR = currentExtent2.r;
00330 result[i] = Extent(newExtentL+backoffTo2, newExtentR);
00331 ++i;
00332 for (; i<depth2; i++) {
00333 result[i] = shape2[i];
00334 }
00335 }
00336 }
00337 }
00338
00339 void
00340 VisualNode::setShape(Shape* s) {
00341 if (shape != s)
00342 Shape::deallocate(shape);
00343 shape = s;
00344 shape->computeBoundingBox();
00345 }
00346
00347 void
00348 VisualNode::computeShape(const NodeAllocator& na, VisualNode* root) {
00349 int numberOfShapes = getNumberOfChildren();
00350 Extent extent(Layout::extent);
00351
00352 int maxDepth = 0;
00353 for (int i = numberOfShapes; i--;)
00354 maxDepth = std::max(maxDepth, getChild(na,i)->getShape()->depth());
00355 Shape* mergedShape;
00356 if (getShape() && getShape()->depth() >= maxDepth+1) {
00357 mergedShape = getShape();
00358 mergedShape->setDepth(maxDepth+1);
00359 } else {
00360 mergedShape = Shape::allocate(maxDepth+1);
00361 }
00362
00363 if (numberOfShapes == 1) {
00364 getChild(na,0)->setOffset(0);
00365 const Shape* childShape = getChild(na,0)->getShape();
00366 for (int i=childShape->depth(); i--;)
00367 (*mergedShape)[i+1] = (*childShape)[i];
00368 (*mergedShape)[1].extend(- extent.l, - extent.r);
00369 setShape(mergedShape);
00370 } else {
00371
00372
00373
00374
00375
00376
00377 assert(root->copy != NULL);
00378 Region r(*root->copy);
00379 std::pair<int,int>* alpha =
00380 r.alloc<std::pair<int,int> >(numberOfShapes);
00381
00382
00383 int width = 0;
00384
00385 Extent* currentShapeL = r.alloc<Extent>(maxDepth);
00386 int ldepth = getChild(na,0)->getShape()->depth();
00387 for (int i=ldepth; i--;)
00388 currentShapeL[i] = (*getChild(na,0)->getShape())[i];
00389
00390
00391
00392 Shape* rShape = getChild(na,numberOfShapes-1)->getShape();
00393 int rdepth = rShape->depth();
00394 for (int i=rdepth; i--;)
00395 (*mergedShape)[i+1] = (*rShape)[i];
00396 Extent* currentShapeR = &(*mergedShape)[1];
00397
00398 for (int i = 1; i < numberOfShapes; i++) {
00399
00400
00401
00402
00403
00404
00405
00406 Shape* nextShapeL = getChild(na,i)->getShape();
00407 int nextAlphaL =
00408 Layouter::getAlpha<Extent*,Shape>(¤tShapeL[0], ldepth,
00409 *nextShapeL, nextShapeL->depth());
00410 Layouter::merge<Extent*,Shape>(¤tShapeL[0],
00411 ¤tShapeL[0], ldepth,
00412 *nextShapeL, nextShapeL->depth(),
00413 nextAlphaL);
00414 ldepth = std::max(ldepth,nextShapeL->depth());
00415 alpha[i].first = nextAlphaL - width;
00416 width = nextAlphaL;
00417
00418
00419
00420 Shape* nextShapeR = getChild(na,numberOfShapes-1-i)->getShape();
00421 int nextAlphaR =
00422 Layouter::getAlpha<Shape,Extent*>(*nextShapeR, nextShapeR->depth(),
00423 ¤tShapeR[0], rdepth);
00424 Layouter::merge<Shape,Extent*>(¤tShapeR[0],
00425 *nextShapeR, nextShapeR->depth(),
00426 ¤tShapeR[0], rdepth,
00427 nextAlphaR);
00428 rdepth = std::max(rdepth,nextShapeR->depth());
00429 alpha[numberOfShapes - i].second = nextAlphaR;
00430 }
00431
00432
00433 (*mergedShape)[1].extend(- extent.l, - extent.r);
00434
00435
00436
00437
00438
00439 int halfWidth = false ? 0 : width / 2;
00440 (*mergedShape)[1].move(- halfWidth);
00441
00442
00443
00444
00445
00446
00447
00448 int offset = - halfWidth;
00449 getChild(na,0)->setOffset(offset);
00450 for (int i = 1; i < numberOfShapes; i++) {
00451 offset += (alpha[i].first + alpha[i].second) / 2;
00452 getChild(na,i)->setOffset(offset);
00453 }
00454 setShape(mergedShape);
00455 }
00456 }
00457
00458 size_t
00459 VisualNode::size(void) const {
00460 size_t s = sizeof(*this);
00461 s += sizeof(Node*)*getNumberOfChildren();
00462 if (shape && shape != Shape::leaf && shape != Shape::hidden) {
00463 s += sizeof(Shape)+sizeof(Extent)*(shape->depth()-1);
00464 }
00465 if (copy)
00466 s += static_cast<Space*>(Support::funmark(copy))->allocated();
00467 s += (choice != NULL ? choice->size() : 0);
00468 return s;
00469 }
00470
00471 }}
00472
00473