6 #include "branchitem.h"
7 #include "math.h" // atan
8 #include "misc.h" // max
10 /////////////////////////////////////////////////////////////////
12 /////////////////////////////////////////////////////////////////
14 int XLinkObj::arrowSize = 6; // make instances
15 int XLinkObj::clickBorder = 8;
16 int XLinkObj::pointRadius = 10;
17 int XLinkObj::d_control = 300;
19 XLinkObj::XLinkObj (QGraphicsItem* parent,Link *l):MapObj(parent)
21 //qDebug()<< "Const XLinkObj (parent,Link)";
28 XLinkObj::~XLinkObj ()
30 //qDebug() << "Destr XLinkObj";
36 delete (pointerBegin);
40 void XLinkObj::init ()
46 QPen pen = link->getPen();
48 path = scene()->addPath (QPainterPath(), pen, Qt::NoBrush);
49 path->setZValue (dZ_XLINK);
51 pointerBegin = new ArrowObj(this);
52 pointerBegin->setPen( pen );
53 pointerBegin->setUseFixedLength( true );
54 pointerBegin->setFixedLength( 0 );
56 pointerEnd = new ArrowObj(this);
57 pointerEnd->setPen( pen );
58 pointerEnd->setUseFixedLength( true );
59 pointerEnd->setFixedLength( 0 );
61 pen.setStyle (Qt::SolidLine);
62 poly = scene()->addPolygon (QPolygonF(), pen, pen.color());
63 poly->setZValue (dZ_XLINK);
65 // Control points for bezier path
66 // (We have at least a begin branch, consider its orientation)
70 ctrl_p0 = scene()->addEllipse (
72 clickBorder*2, clickBorder*2,
74 ctrl_p1 = scene()->addEllipse (
76 clickBorder*2, clickBorder*2,
79 beginOrient = endOrient=LinkableMapObj::UndefinedOrientation;
81 pen.setStyle (Qt::DashLine);
83 curSelection = Unselected;
88 QPointF XLinkObj::getAbsPos()
104 void XLinkObj::setStyleBegin(const QString &s)
106 pointerBegin->setStyleEnd( s );
109 void XLinkObj::setStyleBegin(ArrowObj::OrnamentStyle os)
111 pointerBegin->setStyleEnd( os );
114 ArrowObj::OrnamentStyle XLinkObj::getStyleBegin()
116 return pointerBegin->getStyleEnd();
119 void XLinkObj::setStyleEnd(const QString &s)
121 pointerEnd->setStyleEnd( s );
124 void XLinkObj::setStyleEnd(ArrowObj::OrnamentStyle os)
126 pointerEnd->setStyleEnd( os );
129 ArrowObj::OrnamentStyle XLinkObj::getStyleEnd()
131 return pointerEnd->getStyleEnd();
134 QPointF XLinkObj::getBeginPos()
139 QPointF XLinkObj::getEndPos()
144 void XLinkObj::move (QPointF p)
146 switch (curSelection)
160 void XLinkObj::setEnd (QPointF p)
165 void XLinkObj::setSelection (CurrentSelection s)
171 void XLinkObj::setSelection (int cp)
178 qWarning()<<"XLO::setSelection cp="<<cp;
181 void XLinkObj::updateXLink()
186 BranchObj *beginBO=NULL;
187 BranchObj *endBO=NULL;
188 BranchItem *bi=link->getBeginBranch();
189 if ( bi) beginBO=(BranchObj*)(bi->getLMO());
190 bi=link->getEndBranch();
191 if (bi) endBO=(BranchObj*)(bi->getLMO());
195 if (beginOrient != LinkableMapObj::UndefinedOrientation &&
196 beginOrient != beginBO->getOrientation() )
198 beginOrient = beginBO->getOrientation();
202 if (endOrient != LinkableMapObj::UndefinedOrientation &&
203 endOrient != endBO->getOrientation() )
205 endOrient = endBO->getOrientation();
210 // Only one of the linked branches is visible
211 // Draw arrowhead //FIXME-3 missing shaft of arrow
212 BranchObj *bo=(BranchObj*)(visBranch->getLMO());
215 a=b=bo->getChildRefPos();
218 if (bo->getOrientation()==LinkableMapObj::RightOfCenter)
220 b.setX (b.x() + 2*arrowSize);
224 QPointF (b.x(), b.y() - arrowSize) <<
225 QPointF (b.x() + arrowSize, b.y()) <<
226 QPointF (b.x(), b.y() + arrowSize) <<
229 poly->setPolygon(pa);
232 b.setX (b.x() - 2*arrowSize);
236 QPointF (b.x(), b.y() - arrowSize) <<
237 QPointF (b.x() - arrowSize, b.y()) <<
238 QPointF (b.x(), b.y() + arrowSize) <<
241 poly->setPolygon (pa);
245 // Both linked branches are visible
247 // If a link is just drawn in the editor,
248 // we have already a beginBranch
249 if (beginBO) beginPos=beginBO->getChildRefPos();
250 if (endBO) endPos=endBO->getChildRefPos();
252 if (beginBO && endBO)
254 pointerBegin->move(beginPos + c0 );
255 pointerBegin->setEndPoint(beginPos);
257 pointerEnd->move(endPos + c1 );
258 pointerEnd->setEndPoint(endPos);
262 // Update control points for bezier
263 QPainterPath p(beginPos);
264 p.cubicTo ( beginPos + c0, endPos + c1, endPos);
269 // Go back to create closed curve,
270 // needed for intersection check:
271 clickPath.cubicTo ( endPos + c1, beginPos + c0, beginPos);
273 QPen pen=link->getPen();
275 poly->setBrush (pen.color() );
277 pointerBegin->setPen( pen );
278 pointerEnd->setPen( pen );
280 pen.setStyle (Qt::SolidLine);
284 beginPos.x() + c0.x() - pointRadius/2, beginPos.y() + c0.y() - pointRadius/2,
285 pointRadius, pointRadius );
286 ctrl_p0->setPen (pen);
287 ctrl_p0->setBrush (pen.color() );
290 endPos.x() + c1.x() - pointRadius/2, endPos.y() + c1.y() - pointRadius/2,
291 pointRadius, pointRadius );
292 ctrl_p1->setPen (pen);
293 ctrl_p1->setBrush (pen.color() );
295 BranchItem *bi_begin=link->getBeginBranch();
296 BranchItem *bi_end =link->getEndBranch();
297 if (bi_begin && bi_end && link->getState()==Link::activeXLink)
298 // Note: with MapObj being a GraphicsItem now, maybe better reparent the xlinkobj
299 // line->setZValue (dZ_DEPTH * max(bi_begin->depth(),bi_end->depth()) + dZ_XLINK);
300 path->setZValue (dZ_XLINK);
302 path->setZValue (dZ_XLINK);
307 void XLinkObj::positionBBox()
311 void XLinkObj::calcBBoxSize()
315 void XLinkObj::setVisibility (bool b)
317 if (stateVis==FullShowControls)
321 pointerBegin->setUseFixedLength( false );
322 pointerEnd->setUseFixedLength( false );
327 pointerBegin->setUseFixedLength( true );
328 pointerBegin->setFixedLength( 0 );
329 pointerEnd->setUseFixedLength( true );
330 pointerEnd->setFixedLength( 0 );
333 MapObj::setVisibility (b);
336 if (stateVis==OnlyBegin)
340 pointerBegin->hide();
343 else if (stateVis==OnlyEnd)
347 pointerBegin->hide();
354 pointerBegin->show();
362 pointerBegin->hide();
368 void XLinkObj::setVisibility ()
370 BranchItem* beginBI=link->getBeginBranch();
371 BranchObj* beginBO=NULL;
372 if (beginBI) beginBO=(BranchObj*)(beginBI->getLMO());
374 BranchObj* endBO=NULL;
375 BranchItem* endBI=link->getEndBranch();
376 if (endBI) endBO=(BranchObj*)(endBI->getLMO());
377 if (beginBO && endBO)
379 if(beginBO->isVisibleObj() && endBO->isVisibleObj())
380 { // Both ends are visible
382 if (curSelection != Unselected)
383 stateVis=FullShowControls;
386 setVisibility (true);
389 if(!beginBO->isVisibleObj() && !endBO->isVisibleObj())
390 { //None of the ends is visible
393 setVisibility (false);
395 { // Just one end is visible, draw a symbol that shows
396 // that there is a link to a scrolled branch
397 if (beginBO->isVisibleObj())
407 setVisibility (true);
413 void XLinkObj::initC0()
416 BranchItem *beginBranch = link->getBeginBranch();
417 if ( !beginBranch ) return;
418 BranchObj *bo = beginBranch->getBranchObj();
420 if ( bo->getOrientation() == LinkableMapObj::RightOfCenter )
421 c0 = QPointF ( d_control, 0);
423 c0 = QPointF ( -d_control, 0);
426 void XLinkObj::initC1()
429 BranchItem *endBranch = link->getEndBranch();
430 if (!endBranch) return;
431 BranchObj *bo = endBranch->getBranchObj();
433 if ( bo->getOrientation() == LinkableMapObj::RightOfCenter )
434 c1 = QPointF ( d_control, 0);
436 c1 = QPointF ( -d_control, 0);
439 void XLinkObj::setC0(const QPointF &p)
444 QPointF XLinkObj::getC0()
449 void XLinkObj::setC1(const QPointF &p)
454 QPointF XLinkObj::getC1()
459 int XLinkObj::ctrlPointInClickBox (const QPointF &p)
461 CurrentSelection oldSel=curSelection;
464 QRectF r(p.x() - clickBorder, p.y() - clickBorder,
465 clickBorder *2, clickBorder*2) ;
467 if (curSelection==C0 || curSelection==C1)
469 // If Cx selected, check both ctrl points
471 if (getClickPath().intersects (r) ) ret=0;
473 if (getClickPath().intersects (r) ) ret=1;
479 bool XLinkObj::isInClickBox (const QPointF &p)
481 // Return, if not visible at all...
482 if (stateVis==Hidden) return false;
484 CurrentSelection oldSel=curSelection;
487 QRectF r(p.x() - clickBorder, p.y() - clickBorder,
488 clickBorder *2, clickBorder*2) ;
492 case FullShowControls:
493 // If Cx selected, check both ctrl points
494 if (ctrlPointInClickBox(p) >-1) b=true;
496 // Enable selecting the path, when a ctrl point is already selected
497 if (!b && curSelection!=Unselected && clickPath.intersects (r)) b=true;
499 case OnlyBegin || OnlyEnd:
500 // not selected, only partially visible
501 if (poly->boundingRect().contains(p) )
505 // not selected, but path is fully visible
507 if (getClickPath().intersects (r) ) b=true;
514 QPainterPath XLinkObj::getClickPath() // also needs mirroring if oriented left. Create method to generate the coordinates
517 switch (curSelection)
520 p.addEllipse (beginPos + c0,15,15);
524 p.addEllipse (endPos + c1,15,15);