5 #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 // qDebug() << "Destr XLinkObj";
34 delete (pointerBegin);
43 QPen pen = link->getPen();
45 path = scene()->addPath(QPainterPath(), pen, Qt::NoBrush);
46 path->setZValue(dZ_XLINK);
48 pointerBegin = new ArrowObj(this);
49 pointerBegin->setPen(pen);
50 pointerBegin->setUseFixedLength(true);
51 pointerBegin->setFixedLength(0);
53 pointerEnd = new ArrowObj(this);
54 pointerEnd->setPen(pen);
55 pointerEnd->setUseFixedLength(true);
56 pointerEnd->setFixedLength(0);
58 pen.setStyle(Qt::SolidLine);
59 poly = scene()->addPolygon(QPolygonF(), pen, pen.color());
60 poly->setZValue(dZ_XLINK);
62 // Control points for bezier path
63 // (We have at least a begin branch, consider its orientation)
67 ctrl_p0 = scene()->addEllipse(c0.x(), c0.y(), clickBorder * 2,
68 clickBorder * 2, pen, pen.color());
69 ctrl_p1 = scene()->addEllipse(c1.x(), c1.y(), clickBorder * 2,
70 clickBorder * 2, pen, pen.color());
72 beginOrient = endOrient = LinkableMapObj::UndefinedOrientation;
74 pen.setStyle(Qt::DashLine);
76 curSelection = Unselected;
81 QPointF XLinkObj::getAbsPos()
83 switch (curSelection) {
96 void XLinkObj::setStyleBegin(const QString &s) { pointerBegin->setStyleEnd(s); }
98 void XLinkObj::setStyleBegin(ArrowObj::OrnamentStyle os)
100 pointerBegin->setStyleEnd(os);
103 ArrowObj::OrnamentStyle XLinkObj::getStyleBegin()
105 return pointerBegin->getStyleEnd();
108 void XLinkObj::setStyleEnd(const QString &s) { pointerEnd->setStyleEnd(s); }
110 void XLinkObj::setStyleEnd(ArrowObj::OrnamentStyle os)
112 pointerEnd->setStyleEnd(os);
115 ArrowObj::OrnamentStyle XLinkObj::getStyleEnd()
117 return pointerEnd->getStyleEnd();
120 QPointF XLinkObj::getBeginPos() { return beginPos; }
122 QPointF XLinkObj::getEndPos() { return endPos; }
124 void XLinkObj::move(QPointF p)
126 switch (curSelection) {
139 void XLinkObj::setEnd(QPointF p) { endPos = p; }
141 void XLinkObj::setSelection(CurrentSelection s)
147 void XLinkObj::setSelection(int cp)
154 qWarning() << "XLO::setSelection cp=" << cp;
157 void XLinkObj::updateXLink()
162 BranchObj *beginBO = NULL;
163 BranchObj *endBO = NULL;
164 BranchItem *bi = link->getBeginBranch();
166 beginBO = (BranchObj *)(bi->getLMO());
167 bi = link->getEndBranch();
169 endBO = (BranchObj *)(bi->getLMO());
172 if (beginOrient != LinkableMapObj::UndefinedOrientation &&
173 beginOrient != beginBO->getOrientation())
175 beginOrient = beginBO->getOrientation();
178 if (endOrient != LinkableMapObj::UndefinedOrientation &&
179 endOrient != endBO->getOrientation())
181 endOrient = endBO->getOrientation();
185 // Only one of the linked branches is visible
186 // Draw arrowhead //FIXME-3 missing shaft of arrow
187 BranchObj *bo = (BranchObj *)(visBranch->getLMO());
191 a = b = bo->getChildRefPos();
193 if (bo->getOrientation() == LinkableMapObj::RightOfCenter) {
194 b.setX(b.x() + 2 * arrowSize);
196 pa << a << b << QPointF(b.x(), b.y() - arrowSize)
197 << QPointF(b.x() + arrowSize, b.y())
198 << QPointF(b.x(), b.y() + arrowSize) << b << a;
199 poly->setPolygon(pa);
202 b.setX(b.x() - 2 * arrowSize);
204 pa << a << b << QPointF(b.x(), b.y() - arrowSize)
205 << QPointF(b.x() - arrowSize, b.y())
206 << QPointF(b.x(), b.y() + arrowSize) << b << a;
207 poly->setPolygon(pa);
211 // Both linked branches are visible
213 // If a link is just drawn in the editor,
214 // we have already a beginBranch
216 beginPos = beginBO->getChildRefPos();
218 endPos = endBO->getChildRefPos();
220 if (beginBO && endBO) {
221 pointerBegin->move(beginPos + c0);
222 pointerBegin->setEndPoint(beginPos);
224 pointerEnd->move(endPos + c1);
225 pointerEnd->setEndPoint(endPos);
229 // Update control points for bezier
230 QPainterPath p(beginPos);
231 p.cubicTo(beginPos + c0, endPos + c1, endPos);
236 // Go back to create closed curve,
237 // needed for intersection check:
238 clickPath.cubicTo(endPos + c1, beginPos + c0, beginPos);
240 QPen pen = link->getPen();
242 poly->setBrush(pen.color());
244 pointerBegin->setPen(pen);
245 pointerEnd->setPen(pen);
247 pen.setStyle(Qt::SolidLine);
249 ctrl_p0->setRect(beginPos.x() + c0.x() - pointRadius / 2,
250 beginPos.y() + c0.y() - pointRadius / 2, pointRadius,
252 ctrl_p0->setPen(pen);
253 ctrl_p0->setBrush(pen.color());
255 ctrl_p1->setRect(endPos.x() + c1.x() - pointRadius / 2,
256 endPos.y() + c1.y() - pointRadius / 2, pointRadius,
258 ctrl_p1->setPen(pen);
259 ctrl_p1->setBrush(pen.color());
261 BranchItem *bi_begin = link->getBeginBranch();
262 BranchItem *bi_end = link->getEndBranch();
263 if (bi_begin && bi_end && link->getState() == Link::activeXLink)
264 // Note: with MapObj being a GraphicsItem now, maybe better reparent the
265 // xlinkobj line->setZValue (dZ_DEPTH *
266 // max(bi_begin->depth(),bi_end->depth()) + dZ_XLINK);
267 path->setZValue(dZ_XLINK);
269 path->setZValue(dZ_XLINK);
274 void XLinkObj::positionBBox() {}
276 void XLinkObj::calcBBoxSize() {}
278 void XLinkObj::setVisibility(bool b)
280 if (stateVis == FullShowControls) {
283 pointerBegin->setUseFixedLength(false);
284 pointerEnd->setUseFixedLength(false);
289 pointerBegin->setUseFixedLength(true);
290 pointerBegin->setFixedLength(0);
291 pointerEnd->setUseFixedLength(true);
292 pointerEnd->setFixedLength(0);
295 MapObj::setVisibility(b);
297 if (stateVis == OnlyBegin) {
300 pointerBegin->hide();
303 else if (stateVis == OnlyEnd) {
306 pointerBegin->hide();
312 pointerBegin->show();
319 pointerBegin->hide();
324 void XLinkObj::setVisibility()
326 BranchItem *beginBI = link->getBeginBranch();
327 BranchObj *beginBO = NULL;
329 beginBO = (BranchObj *)(beginBI->getLMO());
331 BranchObj *endBO = NULL;
332 BranchItem *endBI = link->getEndBranch();
334 endBO = (BranchObj *)(endBI->getLMO());
335 if (beginBO && endBO) {
336 if (beginBO->isVisibleObj() &&
337 endBO->isVisibleObj()) { // Both ends are visible
339 if (curSelection != Unselected)
340 stateVis = FullShowControls;
346 if (!beginBO->isVisibleObj() &&
347 !endBO->isVisibleObj()) { // None of the ends is visible
350 setVisibility(false);
352 else { // Just one end is visible, draw a symbol that shows
353 // that there is a link to a scrolled branch
354 if (beginBO->isVisibleObj()) {
355 stateVis = OnlyBegin;
368 void XLinkObj::initC0()
372 BranchItem *beginBranch = link->getBeginBranch();
375 BranchObj *bo = beginBranch->getBranchObj();
378 if (bo->getOrientation() == LinkableMapObj::RightOfCenter)
379 c0 = QPointF(d_control, 0);
381 c0 = QPointF(-d_control, 0);
384 void XLinkObj::initC1()
388 BranchItem *endBranch = link->getEndBranch();
391 BranchObj *bo = endBranch->getBranchObj();
394 if (bo->getOrientation() == LinkableMapObj::RightOfCenter)
395 c1 = QPointF(d_control, 0);
397 c1 = QPointF(-d_control, 0);
400 void XLinkObj::setC0(const QPointF &p) { c0 = p; }
402 QPointF XLinkObj::getC0() { return c0; }
404 void XLinkObj::setC1(const QPointF &p) { c1 = p; }
406 QPointF XLinkObj::getC1() { return c1; }
408 int XLinkObj::ctrlPointInClickBox(const QPointF &p)
410 CurrentSelection oldSel = curSelection;
413 QRectF r(p.x() - clickBorder, p.y() - clickBorder, clickBorder * 2,
416 if (curSelection == C0 || curSelection == C1) {
417 // If Cx selected, check both ctrl points
419 if (getClickPath().intersects(r))
422 if (getClickPath().intersects(r))
425 curSelection = oldSel;
429 bool XLinkObj::isInClickBox(const QPointF &p)
431 // Return, if not visible at all...
432 if (stateVis == Hidden)
435 CurrentSelection oldSel = curSelection;
438 QRectF r(p.x() - clickBorder, p.y() - clickBorder, clickBorder * 2,
442 case FullShowControls:
443 // If Cx selected, check both ctrl points
444 if (ctrlPointInClickBox(p) > -1)
447 // Enable selecting the path, when a ctrl point is already selected
448 if (!b && curSelection != Unselected && clickPath.intersects(r))
453 // not selected, only partially visible
454 if (poly->boundingRect().contains(p))
458 // not selected, but path is fully visible
460 if (getClickPath().intersects(r))
464 curSelection = oldSel;
469 XLinkObj::getClickPath() // also needs mirroring if oriented left. Create method
470 // to generate the coordinates
473 switch (curSelection) {
475 p.addEllipse(beginPos + c0, 15, 15);
479 p.addEllipse(endPos + c1, 15, 15);
488 QPainterPath XLinkObj::getSelectionPath()
490 return getClickPath();