3 #include "linkablemapobj.h"
10 /////////////////////////////////////////////////////////////////
12 /////////////////////////////////////////////////////////////////
14 LinkableMapObj::LinkableMapObj():MapObj()
16 // cout << "Const LinkableMapObj ()\n";
20 LinkableMapObj::LinkableMapObj(QCanvas* c) :MapObj(c)
22 // cout << "Const LinkableMapObj\n";
26 LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
31 LinkableMapObj::~LinkableMapObj()
39 void LinkableMapObj::delLink()
53 case StylePolyParabel:
62 void LinkableMapObj::init ()
73 orientation=OrientUndef;
78 segment.setAutoDelete (TRUE);
80 QPointArray pa(arcsegs*2+2);
82 bottomline=new QCanvasLine(canvas);
83 bottomline->setPen( QPen(linkcolor, 1) );
84 bottomline->setZ(Z_LINK);
87 // Prepare showing the selection of a MapObj
88 selbox = new QCanvasRectangle (canvas);
89 selbox->setZ(Z_SELBOX);
90 selbox->setBrush( QColor(255,255,0) );
91 selbox->setPen( QPen(QColor(255,255,0) ));
95 hideLinkUnselected=false;
97 topPad=botPad=leftPad=rightPad=0;
100 frame = new FrameObj (canvas);
102 repositionRequest=false;
110 void LinkableMapObj::copy (LinkableMapObj* other)
113 bboxTotal=other->bboxTotal;
114 setLinkStyle(other->style);
115 setLinkColor (other->linkcolor);
116 relPos=other->relPos;
117 useOrientation=other->useOrientation;
121 void LinkableMapObj::setChildObj(LinkableMapObj* o)
126 void LinkableMapObj::setParObj(LinkableMapObj* o)
129 mapEditor=parObj->getMapEditor();
132 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
136 void LinkableMapObj::unsetParObjTmp()
140 bool LinkableMapObj::hasParObjTmp()
142 if (parObjTmpBuf) return true;
146 void LinkableMapObj::setUseRelPos (const bool &b)
151 void LinkableMapObj::setRelPos()
155 relPos.setX (absPos.x() - parObj->getChildPos().x() );
156 relPos.setY (absPos.y() - parObj->getChildPos().y() );
158 parObj->calcBBoxSize();
159 parObj->requestReposition();
163 void LinkableMapObj::setRelPos(const QPoint &p)
167 { parObj->calcBBoxSize();
168 parObj->requestReposition();
172 int LinkableMapObj::getTopPad()
177 int LinkableMapObj::getLeftPad()
182 int LinkableMapObj::getRightPad()
187 LinkStyle LinkableMapObj::getDefLinkStyle ()
189 if (!mapEditor) return StyleUndef;
191 LinkStyle ls=mapEditor->getLinkStyle();
206 case StylePolyParabel:
218 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
220 //if (newstyle=style) return;
225 if (childObj!=NULL && parObj != NULL)
235 l = new QCanvasLine(canvas);
236 l->setPen( QPen(linkcolor, 1) );
244 for (i=0;i<arcsegs;i++)
246 cl = new QCanvasLine(canvas);
247 cl->setPen( QPen(linkcolor, 1) );
248 cl->setPoints( 0,0,i*10,100);
256 pa0.resize (arcsegs+1);
259 p = new QCanvasPolygon(canvas);
260 p->setBrush( linkcolor );
267 // TODO a bit awkward: draw the lines additionally to polygon, to avoid
268 // missing pixels, when polygon is extremly flat
269 l = new QCanvasLine(canvas);
270 l->setPen( QPen(linkcolor, 1) );
277 case StylePolyParabel:
278 p = new QCanvasPolygon(canvas);
279 p->setBrush( linkcolor );
285 pa0.resize (arcsegs*2+2);
286 pa1.resize (arcsegs+1);
287 pa2.resize (arcsegs+1);
289 // TODO a bit awkward: draw the lines additionally
290 // to polygon, to avoid missing pixels,
291 // if polygon is extremly flat
292 for (i=0;i<arcsegs;i++)
294 cl = new QCanvasLine(canvas);
295 cl->setPen( QPen(linkcolor, 1) );
296 cl->setPoints( 0,0,i*10,100);
311 LinkStyle LinkableMapObj::getLinkStyle()
316 void LinkableMapObj::setHideLinkUnselected(bool b)
318 hideLinkUnselected=b;
319 setVisibility (visible);
323 bool LinkableMapObj::getHideLinkUnselected()
325 return hideLinkUnselected;
328 void LinkableMapObj::setLinkPos(LinkPos lp)
333 LinkPos LinkableMapObj::getLinkPos()
339 void LinkableMapObj::setLinkColor()
341 // Overloaded in BranchObj and childs
342 // here only set default color
344 setLinkColor (mapEditor->getDefLinkColor());
347 void LinkableMapObj::setLinkColor(QColor col)
350 bottomline->setPen( QPen(linkcolor, 1) );
355 l->setPen( QPen(col,1));
358 for (cl=segment.first(); cl; cl=segment.next() )
359 cl->setPen( QPen(col,1));
362 p->setBrush( QBrush(col));
363 l->setPen( QPen(col,1));
365 case StylePolyParabel:
366 p->setBrush( QBrush(col));
367 for (cl=segment.first(); cl; cl=segment.next() )
368 cl->setPen( QPen(col,1));
375 QColor LinkableMapObj::getLinkColor()
380 FrameType LinkableMapObj::getFrameType()
382 return frame->getFrameType();
385 void LinkableMapObj::setFrameType(const FrameType &t)
387 frame->setFrameType(t);
393 void LinkableMapObj::setFrameType(const QString &t)
395 frame->setFrameType(t);
401 void LinkableMapObj::setVisibility (bool v)
404 MapObj::setVisibility (v);
407 // We can hide the link, while object is not selected
408 if (hideLinkUnselected && !selected)
420 for (cl=segment.first(); cl; cl=segment.next() )
427 case StylePolyParabel:
428 for (cl=segment.first(); cl; cl=segment.next() )
444 for (cl=segment.first(); cl; cl=segment.next() )
451 case StylePolyParabel:
452 for (cl=segment.first(); cl; cl=segment.next() )
462 void LinkableMapObj::updateLink()
465 // childPos of parent
471 // childPos (by calling setDockPos())
472 // parPos (by calling setDockPos())
474 // drawing of the link itself
476 // updateLink is called from move, but called from constructor we don't
477 // have parents yet...
478 if (style==StyleUndef) return;
480 if (frame->getFrameType() == NoFrame)
487 bottomlineY=bbox.top()+bbox.height() /2; // draw link to middle (of frame)
490 bottomlineY=bbox.bottom()-1; // draw link to bottom of box
494 double p2x,p2y; // Set P2 Before setting
497 p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at
498 p2y=QPoint( parObj->getChildPos() ).y(); // orientation
501 p2x=QPoint( parObj->getParPos() ).x();
502 p2y=QPoint( parObj->getParPos() ).y();
505 LinkOrient orientOld=orientation;
507 // Set orientation, first look for orientation of parent
508 if (parObj->getOrientation() != OrientUndef )
509 // use the orientation of the parent:
510 orientation=parObj->getOrientation();
513 // calc orientation depending on position rel to mapCenter
514 if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
515 orientation=OrientLeftOfCenter;
517 orientation=OrientRightOfCenter;
520 if ((orientation!=orientOld) && (orientOld!= OrientUndef))
522 // Orientation just changed. Reorient this subbranch, because move is called
523 // before updateLink => Position is still the old one, which could lead to
524 // linking of subranch to itself => segfault
526 // Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
527 // no need to reposition now
533 double p1x=parPos.x(); // Link is drawn from P1 to P2
534 double p1y=parPos.y();
536 double vx=p2x - p1x; // V=P2-P1
539 // Draw the horizontal line below heading (from ChildPos to ParPos)
540 bottomline->setPoints (qRound(childPos.x()),
541 qRound(childPos.y()),
546 if (vx > -0.000001 && vx < 0.000001)
550 // "turning point" for drawing polygonal links
551 QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));
561 l->setPoints( qRound (parPos.x()),
567 parabel (pa0, p1x,p1y,p2x,p2y);
569 for (cl=segment.first(); cl; cl=segment.next() )
571 cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
576 pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
577 pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
578 pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
580 // here too, draw line to avoid missing pixels
581 l->setPoints( qRound (parPos.x()),
586 case StylePolyParabel:
587 parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
588 parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
589 for (i=0;i<=arcsegs;i++)
591 // Combine the arrays to a single one
593 pa0[i+arcsegs+1]=pa2[arcsegs-i];
597 for (cl=segment.first(); cl; cl=segment.next() )
599 cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
608 LinkableMapObj* LinkableMapObj::getChildObj()
613 LinkableMapObj* LinkableMapObj::getParObj()
618 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
620 LinkableMapObj *lmo=this;
624 while (!s.isEmpty() )
626 part=s.section(",",0,0);
628 num=part.right(part.length() - 3);
632 return false; // in a subtree there is no center
637 lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
640 lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
644 s=s.right(s.length() - part.length() -1 );
651 void LinkableMapObj::setDockPos()
653 cout <<"LMO::setDockPos()\n";
656 QPoint LinkableMapObj::getChildPos()
661 QPoint LinkableMapObj::getParPos()
666 QPoint LinkableMapObj::getRelPos()
669 /* FIXME not needed? relPos was moved in 1.7.10 from
670 floatobj to linkablemapobj. Before we had:
672 if (!parObj) return QPoint (0,0);
674 absPos.x() - parObj->x(),
675 absPos.y() - parObj->y()
681 void LinkableMapObj::setUseOrientation (const bool &b)
683 if (useOrientation!=b)
690 LinkOrient LinkableMapObj::getOrientation()
695 int LinkableMapObj::getDepth()
700 void LinkableMapObj::setMapEditor (MapEditor *me)
705 MapEditor* LinkableMapObj::getMapEditor ()
710 QPoint LinkableMapObj::getRandPos()
712 // Choose a random position with given distance to parent:
713 double a=rand()%360 * 2 * M_PI / 360;
714 return QPoint ( (int)( + 150*cos (a)),
715 (int)( + 150*sin (a)));
718 void LinkableMapObj::alignRelativeTo (QPoint ref)
720 // FIXME testing, seems not to be used right now...
721 cout << "LMO::alignRelTo ref="<<ref<<endl;
724 void LinkableMapObj::reposition()
728 // only calculate the sizes once. If the deepest LMO changes its height,
729 // all upper LMOs have to change, too.
730 calcBBoxSizeWithChilds();
732 alignRelativeTo ( QPoint (absPos.x(),
733 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
736 // This is only important for moving branches:
737 // For editing a branch it isn't called...
738 alignRelativeTo ( QPoint (absPos.x(),
739 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
743 void LinkableMapObj::requestReposition()
745 if (!repositionRequest)
747 // Pass on the request to parental objects, if this hasn't
749 repositionRequest=true;
750 if (parObj) parObj->requestReposition();
754 void LinkableMapObj::forceReposition()
756 // Sometimes a reposition has to be done immediatly: For example
757 // if the note editor flag changes, there is no user event in mapeditor
758 // which could collect requests for a reposition.
759 // Then we have to call forceReposition()
760 // But no rule without exception: While loading a map or undoing it,
761 // we want to block expensive repositioning, but just do it once at
762 // the end, thus check first:
764 if (mapEditor->isRepositionBlocked()) return;
766 // Pass on the request to parental objects, if this hasn't been done yet
769 parObj->forceReposition();
774 bool LinkableMapObj::repositionRequested()
776 return repositionRequest;
780 void LinkableMapObj::setSelBox()
782 selbox->setX (clickBox.x() );
783 selbox->setY (clickBox.y() );
784 selbox->setSize (clickBox.width(), clickBox.height() );
787 void LinkableMapObj::select()
793 setVisibility (visible);
797 void LinkableMapObj::unselect()
801 // Maybe we have to hide the link:
802 setVisibility (visible);
805 void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
808 double vx=p2x - p1x; // V=P2-P1
811 double dx; // delta x during calculation of parabel
813 double pnx; // next point
817 if (vx > -0.0001 && vx < 0.0001)
823 ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
824 for (i=1;i<=arcsegs;i++)
827 pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
828 ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
834 QString LinkableMapObj::getLinkAttr ()
836 if (hideLinkUnselected)
837 return attribut ("hideLink","true");
839 return attribut ("hideLink","false");