1 
2 
3 
4 /************************************************************************\
5    LabelledNode declaration
6 \************************************************************************/
7 
8 class Shaper;
9 
10 #define LabelledNodeParent IlvListLabel
11 #define LabelledNodeParentPtr IlvListLabel*
12 class LabelledNode: public LabelledNodeParent {
13 private:
14 protected:
15    char* label_;
16    IlvColor* border_;
17    IlvShort bwidth_;
18    XeNodePtr xeNode_;
19    ShapeType shapeType_;
20    Shaper* shaper_;
21 
22    virtual void drawShape(IlvDisplay* dpy, IlvPort* dst,
23 			    IlvPalette* palette, IlvTransformer* t, IlvRect& r)
24 ;
25 
26    virtual void baseBoundingBox(IlvRect& r, IlvTransformer* t=0);
27 public:
28    LabelledNode(XeNodePtr xenode, IlvDisplay* dpy, const IlvPoint& p, char* lbl
29 ,
30 	  IlvShort bwidth, IlvPalette* palette = nil);
~LabelledNode()31    ~LabelledNode() { ; }
32    void label(char*);
label()33    char* label() { return (label_); }
34    void borderColor(char*);
35 
36    void shape(ShapeType type);
shapeType()37    ShapeType shapeType() { return shapeType_; }
38 
borderWidth()39    IlvShort borderWidth() { return bwidth_; }
borderWidth(IlvShort w)40    void borderWidth(IlvShort w) { bwidth_ =  w; }
41 
xeNode()42    XeNodePtr xeNode() { return xeNode_; }
xeNode(XeNodePtr n)43    void xeNode(XeNodePtr n) { xeNode_ = n; }
44 
45    virtual void draw(IlvPort* dst, IlvTransformer* t, IlvRegion* rect=0);
46    virtual void boundingBox(IlvRect& r, IlvTransformer* t=0);
47    virtual IlvBoolean contains(const IlvPoint& p,
48 			       const IlvPoint& tp, IlvTransformer* t);
49    virtual void computeRegion(IlvRegion& r, IlvTransformer* t=0);
50 
51    static LabelledNode* makeShapedNode(XeNodePtr node,
52 				       IlvDisplay* dpy,
53 				       const ShapeType type,
54 				       const IlvPoint& p,
55 				       char* label,
56 				       IlvShort bwidth);
57 
58    DeclareTypeInfo();
59 };
60 
61 typedef enum { FixedPosition = 0x0, RelativePosition = 0x1 } ArcEndType;
62 
63 /************************************************************************\
64    LabelledArc declaration and implementation
65 \************************************************************************/
66 
67 
68 typedef IlvLinkImage ArcRootClass;
69 
70 class TextList;
71 
72 #define RECURSIVE_BEZIER_ARCS 1
73 // IlvDisplay::drawArrow(dst, transform, start, end, atPos) requires
74 // atPos in the range [0.0,1.0].   0.0 means draw the arrow at the
75 // beginning of line, 1.0 means draw at end...
76 
77 const float ArrowAtStart = 0.0;
78 const float ArrowAtEnd = 1.0;
79 
80 const int NodeBorderAllowance = 4;
81 
82 #define LabelledArcParent IlvLinkImage
83 #define LabelledArcParentPtr IlvLinkImage*
84 class LabelledArc: public LabelledArcParent {
85 protected:
86    XeArcPtr arc;
87    char* label;
88    Boolean labelVisible;
89 
90    char* labelColorString;
91    IlvColor* labelColor;
92 
93    TextList* tlist;
94 #if RECURSIVE_BEZIER_ARCS
95    IlvPoint _points[7];
96    IlvShort _nPoints;
97    IlvPoint _labelOrigin;
98 #else
99    IlvPoint _points[4];
100    IlvInt _nPoints;
101    IlvPoint _labelOrigin;
102 #endif
103 
104    IlvBoolean arrowContains(const IlvPoint& p,
105 			    const IlvPoint& tp, IlvTransformer*t=0);
106 
107    virtual IlvBoolean arcContains(const IlvPoint& p,
108 				  const IlvPoint& tp, IlvTransformer*t=0)
109    {
110       IlvBoolean isIn;
111       isIn = IlvPointInLine(p, _points[0], _points[1]);
112       if (!isIn) {
113 	 isIn = arrowContains(p, tp, t);
114       }
115       return isIn;
116    }
117 
118    virtual IlvBoolean labelContains(const IlvPoint& p,
119 				    const IlvPoint& tp, IlvTransformer*t=0)
120    {
121       IlvRect r;
122       labelBoundingBox(r, t);
123       IlvBoolean isIn;
124       if (t) {
125 	 isIn = r.contains(tp);
126       } else {
127 	 isIn = r.contains(p);
128       }
129       return isIn;
130    }
131 
132    // calculate the origination point for the label, using the
133    // indicated transformation
134    virtual void getLabelOrigin(IlvPoint& origin, IlvTransformer* t=0)
135    {
136       IlvRect r;
137       arcBoundingBox(r, t);
138       origin.move(r.centerx(), r.centery());
139    }
140 
141    virtual void arrowPoints(IlvPoint* points, IlvTransformer* t=0)
142    {
143       // This should really calculate the points then apply the transformer...
144       IlvPoint from = _points[0], to = _points[1];
145       if (t) {
146 	 t->apply(from);
147 	 t->apply(to);
148       }
149       IlvComputeArrow(from, to, ArrowAtEnd, points);
150    }
151 
152    virtual void arrowBoundingBox(IlvRect& r, IlvTransformer* t=0)
153    {
154       IlvPoint pts[3];
155       arrowPoints(pts, t);
156       r.resize(0,0);
157       r.move(pts[0]);
158       r.add(pts[1]);
159       r.add(pts[2]);
160    }
161 
162    virtual void arcBoundingBox(IlvRect& r, IlvTransformer* t=0)
163    {
164       r.move(_points[0]);
165       r.resize(0,0);
166       r.add(_points[1]);
167       if (t) t->apply(r);
168       IlvRect arrowBox;
169       arrowBoundingBox(arrowBox, t);
170       if (arrowBox.w() != 0 && arrowBox.h() != 0) {
171 	 r.add(arrowBox);
172       }
173    }
174    // find the label's origin relative to the non-transformed bounding
175    // box, then calculate the label's bounding box using the
176    // indicated transformation...
177    virtual void labelBoundingBox(IlvRect& r, IlvTransformer* t=0);
178 
179    virtual void drawArrow(IlvPort* dst, IlvTransformer* t=0, IlvRegion* = 0)
180    {
181       IlvPoint start = _points[0], end = _points[1];
182       if (t) {
183 	 t->apply(start);
184 	 t->apply(end);
185       }
186       getDisplay()->drawArrow(dst, getPalette(), start, end, ArrowAtEnd);
187    }
188 
189    virtual void drawArc(IlvPort* dst, IlvTransformer* t=0, IlvRegion* rect=0);
190 
191    virtual void drawLabel(IlvPort* dst, IlvTransformer* t, IlvRegion* clip=0);
192 
193    virtual void computePoints(IlvGraphic* f, IlvGraphic* t);
194 
195 public:
196    LabelledArc(XeArcPtr owner, IlvDisplay* dpy, char* lbl,
197 	       UIPtr tail, UIPtr head, Boolean showLabel = True);
198    ~LabelledArc();
199 
owner()200    XeArcPtr owner() { return arc; }
201 
getLabel()202    char* getLabel() { return label; }
203    void  setLabel(char* s);
204 
getLabelColor()205    char* getLabelColor() { return labelColorString; }
206    void setLabelColor(char* c);
207 
getLabelVisible()208    Boolean getLabelVisible() { return labelVisible; }
209    void setLabelVisible(Boolean v);
210 
211    virtual IlvBoolean contains(const IlvPoint& p,
212 			       const IlvPoint& tp, IlvTransformer*t =0);
213    virtual void draw(IlvPort* dst, IlvTransformer* t=0, IlvRegion* rect=0);
214    virtual void boundingBox(IlvRect&, IlvTransformer*t =0);
215    virtual void computeRegion(IlvRegion& r, IlvTransformer* t);
216 
217    DeclareTypeInfo();
218 
219 };
220 
221 /************************************************************************\
222  sibling computation code -- perhaps this should be a nested class of arcs
223 \************************************************************************/
224 
225 class SiblingList {
226 protected:
227    XeArcPtr* arcs;
228    int nSlots;
229    int nArcs;
230 
231    void listAppend(XeArcPtr sib);
232    void listRemove(XeArcPtr sib);
233 public:
SiblingList()234    SiblingList() { nSlots = 0; nArcs = 0; arcs = nil; }
~SiblingList()235    ~SiblingList() { delete arcs; }
236 
count()237    int count() { return nArcs; }
max()238    int max() { return nSlots; }
239 
240    void insert(XeArcPtr sib);
241    void remove(XeArcPtr sib);
242    int rank(XeArcPtr);
243 
isSibling(XeArcPtr sib)244    IlvBoolean isSibling(XeArcPtr sib)
245    {
246       IlvBoolean isSib = IlvFalse;
247       for(int i = 0; i < nArcs; i++) {
248 	 if (arcs[i] == sib) {
249 	    isSib = IlvTrue;
250 	    break;
251 	 }
252       }
253       return isSib;
254    }
255 };
256 
257 
258 #if RECURSIVE_BEZIER_ARCS
259 const IlvFloat RankedArcArrowPosition = ArrowAtEnd;
260 #else
261 const IlvFloat RankedArcArrowPosition = 0.6;
262 #endif
263 
264 #define RankedArcParent LabelledArc
265 #define RankedArcParentPtr LabelledArc*
266 class RankedArc: public RankedArcParent {
267 protected:
268 
269    IlvGraphic* _selfNode;
270 #if !RECURSIVE_BEZIER_ARCS
271    EllipseInfo* _eInfo;
272 #endif
273    int currentRank;
274 
275    // Compute the control points for our curve based on rank and
276    // current position of head and tail of arc
277    virtual void computePoints(IlvGraphic* f, IlvGraphic* t);
278 
279    virtual void arrowPoints(IlvPoint* points, IlvTransformer* t=0) {
280       // This should really calculate the points then apply the transformer...
281       IlvPoint from, to;
282       IlvFloat arrowPos = ArrowAtEnd;
283       if (currentRank == 0 && !selfish()) {
284 	 RankedArcParent::arrowPoints(points, t);
285 	 return;
286       }
287       if (selfish()) {
288 #if RECURSIVE_BEZIER_ARCS
289 	 arrowPos = RankedArcArrowPosition;
290 	 from = _points[5];
291 	 to = _points[6];
292 #else
293 	 arrowPos = RankedArcArrowPosition;
294 	 from = _eInfo->startArrow();
295 	 to = _eInfo->endArrow();
296 #endif
297       } else {
298 	 from = _points[2];
299 	 to = _points[3];
300       }
301       if (t) {
302 	 t->apply(from);
303 	 t->apply(to);
304       }
305       IlvComputeArrow(from, to, arrowPos, points);
306    }
307 
computeRank()308    int computeRank() {
309       return owner()->siblings() ? owner()->siblings()->rank(owner()): 0;
310    }
311 
selfish()312    IlvBoolean selfish() { return _selfNode ? IlvTrue : IlvFalse; }
313 
314    virtual IlvBoolean arcContains(const IlvPoint& p,
315 				  const IlvPoint& tp, IlvTransformer*t=0)
316    {
317       IlvBoolean isIn = IlvFalse;
318       currentRank = computeRank();
319       IlvGraphic* tail = getFrom();
320       IlvGraphic* head = getTo();
321       computePoints(tail, head);
322       if (currentRank == 0 && !selfish()) {
323 	 isIn = RankedArcParent::arcContains(p, tp, t);
324       } else {
325 	 if (t) {
326 #if RECURSIVE_BEZIER_ARCS
327 	    IlvPoint points[8];
328 #else
329 	    IlvPoint points[4];
330 #endif
331 	    for (int i = 0; i < _nPoints; i++) {
332 	       points[i] = _points[i];
333 	       t->apply(points[i]);
334 	    }
335 	    // check the "transformed point" supplied by Views manager...
336 #if RECURSIVE_BEZIER_ARCS
337 	    isIn = IlvPointInSpline(tp, _nPoints, points);
338 #else
339 	    if (selfish()) {
340 	       IlvRect r = _eInfo->rect();
341 	       t->apply(r);
342 	       isIn = PointOnArc(tp, r, _eInfo->startAngle(),
343 				 _eInfo->deltaAngle(), /* tolerance */ 2);
344 	    } else {
345 	       isIn = IlvPointInSpline(tp, _nPoints, points);
346 	    }
347 #endif
348 	 } else {
349 #if RECURSIVE_BEZIER_ARCS
350 	    isIn = IlvPointInSpline(p, _nPoints, _points);
351 #else
352 	    if (selfish()) {
353 	       isIn = PointOnArc(p, _eInfo->rect(), _eInfo->startAngle(),
354 				 _eInfo->deltaAngle(), /* tolerance */ 2);
355 	    } else {
356 	       isIn = IlvPointInSpline(p, _nPoints, _points);
357 	    }
358 #endif
359 	 }
360 	 if (!isIn) {
361 	    isIn = arrowContains(p, tp, t);
362 	 }
363       }
364       return isIn;
365    }
366 
367    // calculate the origination point for the label, using the
368    // indicated transformation
369    virtual void getLabelOrigin(IlvPoint& origin, IlvTransformer* t=0)
370    {
371       currentRank = computeRank();
372       IlvGraphic* tail = getFrom();
373       IlvGraphic* head = getTo();
374       computePoints(tail, head);
375       if (currentRank == 0 && !selfish()) {
376 	 RankedArcParent::getLabelOrigin(origin, t);
377       } else {
378 	 origin = _labelOrigin;
379 	 if (t) {
380 	    t->apply(origin);
381 	 }
382       }
383    }
384 
385    virtual void arcBoundingBox(IlvRect& r, IlvTransformer* t=0)
386    {
387       currentRank = computeRank();
388       IlvGraphic* tail = getFrom();
389       IlvGraphic* head = getTo();
390       computePoints(tail, head);
391       if (currentRank == 0 && !selfish()) {
392 	 RankedArcParent::arcBoundingBox(r, t);
393       } else {
394 #if RECURSIVE_BEZIER_ARCS
395 	 r.move(_points[0]);
396 	 r.resize(0,0);
397 	 r.add(_points[1]);
398 	 r.add(_points[2]);
399 	 r.add(_points[3]);
400 	 if (selfish()) { // only valid for self arcs...
401 	    r.add(_points[4]);
402 	    r.add(_points[5]);
403 	    r.add(_points[6]);
404 	 }
405 #else
406 	 if (selfish()) {
407 	    IlvComputeArcBBox(_eInfo->rect(),
408 			      _eInfo->startAngle(),
409 			      _eInfo->deltaAngle(),
410 			      r);
411 	 } else {
412 	    r.move(_points[0]);
413 	    r.resize(0,0);
414 	    r.add(_points[1]);
415 	    r.add(_points[2]);
416 	    r.add(_points[3]);
417 	 }
418 #endif
419 	 IlvRect arrowBox;
420 	 arrowBoundingBox(arrowBox, 0);
421 	 r.add(arrowBox);
422 	 if (t) t->apply(r);
423       }
424    }
425 
426    virtual void drawArc(IlvPort* dst, IlvTransformer* t=0, IlvRegion* rect=0)
427    {
428       currentRank = computeRank();
429       IlvGraphic* tail = getFrom();
430       IlvGraphic* head = getTo();
431       computePoints(tail, head);
432       if (currentRank == 0 && !selfish()) {
433 	 RankedArcParent::drawArc(dst, t, rect);
434       } else {
435 	 // how do we draw the arrow???
436 	 drawArrow(dst, t, rect);
437 	 drawRankedArc(currentRank, dst, t, rect);
438       }
439    }
440 
441    virtual void drawRankedArc(int rank, IlvPort* dst, IlvTransformer* t=0, IlvR
442 egion* rect=0)
443    {
444 #if RECURSIVE_BEZIER_ARCS
445       if (selfish() || rank > 0) {
446 	 if (!t) {
447 	    getDisplay()->drawBezier(dst, getPalette(), _nPoints, _points);
448 	 } else {
449 	    IlvPoint points[8];
450 	    for (int i = 0; i < _nPoints; i++) {
451 	       points[i] = _points[i];
452 	       t->apply(points[i]);
453 	    }
454 	    getDisplay()->drawBezier(dst, getPalette(), _nPoints, points);
455 	 }
456       } else {
457 	 // shouldn't reach this point...
458 	 RankedArcParent::drawArc(dst, t, rect);
459       }
460 #else
461       if (selfish()) {
462 	 IlvRect r = _eInfo->rect();
463 	 if (t) t->apply(r);
464 	 getDisplay()->drawArc(dst, getPalette(), r,
465 			       (IlvFloat) _eInfo->startAngle(),
466 			       (IlvFloat) _eInfo->deltaAngle());
467       } else if (rank > 0) {
468 	 if (t) {
469 	    IlvPoint points[4];
470 	    for (int i = 0; i < _nPoints; i++) {
471 	       points[i] = _points[i];
472 	       t->apply(points[i]);
473 	    }
474 	    getDisplay()->drawBezier(dst, getPalette(), _nPoints, points);
475 	 } else {
476 	    getDisplay()->drawBezier(dst, getPalette(), _nPoints, _points);
477 	 }
478       } else {
479 	 // shouldn't reach this point...
480 	 RankedArcParent::drawArc(dst, t, rect);
481       }
482 #endif
483    }
484 
485    virtual void drawArrow(IlvPort* dst, IlvTransformer* t=0, IlvRegion* r=0)
486    {
487       IlvBoolean selfArc = selfish();
488       if (!selfArc && currentRank == 0) {
489 	 RankedArcParent::drawArrow(dst, t, r);
490       } else {
491 	 IlvPoint start, end;
492 	 IlvFloat arrowPos = ArrowAtEnd;
493 #if RECURSIVE_BEZIER_ARCS
494 	 if (selfArc) {
495 	    start = _points[5];
496 	    end = _points[6];
497 	    arrowPos = RankedArcArrowPosition;
498 	 } else {
499 	    start = _points[2];
500 	    end = _points[3];
501 	 }
502 #else
503 	 if (selfArc) {
504 	    start = _eInfo->startArrow();
505 	    end = _eInfo->endArrow();
506 	    arrowPos = RankedArcArrowPosition;
507 	 } else {
508 	    // we use the control points of our spline to determine direction
509 	    // and "slope" of arrow's center...
510 	    start = _points[2];
511 	    end = _points[3];
512 	 }
513 #endif
514 	 if (t) {
515 	    t->apply(start);
516 	    t->apply(end);
517 	 }
518 	 getDisplay()->drawArrow(dst, getPalette(), start, end, arrowPos);
519       }
520    }
521 
522 
523 public:
524    RankedArc(XeArcPtr owner, IlvDisplay* dpy, char* lbl,
525 	     UIPtr tail, UIPtr head, Boolean showLabel = True);
~RankedArc()526    ~RankedArc() {
527       _nPoints = 0;
528 #if !RECURSIVE_BEZIER_ARCS
529       if (_selfNode)
530 	 delete _eInfo;
531 #endif
532    }
533 
534    DeclareTypeInfo();
535 
536 };
537 
538 
539 
540