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 ()
72 orientation=OrientUndef;
77 segment.setAutoDelete (TRUE);
79 QPointArray pa(arcsegs*2+2);
81 bottomline=new QCanvasLine(canvas);
82 bottomline->setPen( QPen(linkcolor, 1) );
83 bottomline->setZ(Z_LINK);
86 // Prepare showing the selection of a MapObj
87 selbox = new QCanvasRectangle (canvas);
88 selbox->setZ(Z_SELBOX);
89 selbox->setBrush( QColor(255,255,0) );
90 selbox->setPen( QPen(QColor(255,255,0) ));
94 hideLinkUnselected=false;
97 frame = new FrameObj (canvas);
99 repositionRequest=false;
102 void LinkableMapObj::copy (LinkableMapObj* other)
105 bboxTotal=other->bboxTotal;
106 setLinkStyle(other->style);
107 setLinkColor (other->linkcolor);
110 void LinkableMapObj::setChildObj(LinkableMapObj* o)
115 void LinkableMapObj::setParObj(LinkableMapObj* o)
118 mapEditor=parObj->getMapEditor();
121 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
125 void LinkableMapObj::unsetParObjTmp()
129 LinkStyle LinkableMapObj::getDefLinkStyle ()
131 LinkStyle ls=mapEditor->getLinkStyle();
146 case StylePolyParabel:
158 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
160 //if (newstyle=style) return;
165 if (childObj!=NULL && parObj != NULL)
175 l = new QCanvasLine(canvas);
176 l->setPen( QPen(linkcolor, 1) );
184 for (i=0;i<arcsegs;i++)
186 cl = new QCanvasLine(canvas);
187 cl->setPen( QPen(linkcolor, 1) );
188 cl->setPoints( 0,0,i*10,100);
196 pa0.resize (arcsegs+1);
199 p = new QCanvasPolygon(canvas);
200 p->setBrush( linkcolor );
208 // a bit awkward: draw the lines additionally to polygon, to avoid
209 // missing pixels, when polygon is extremly flat
210 l = new QCanvasLine(canvas);
211 l->setPen( QPen(linkcolor, 1) );
218 case StylePolyParabel:
219 p = new QCanvasPolygon(canvas);
220 p->setBrush( linkcolor );
226 pa0.resize (arcsegs*2+2);
227 pa1.resize (arcsegs+1);
228 pa2.resize (arcsegs+1);
231 // a bit awkward: draw the lines additionally
232 // to polygon, to avoid missing pixels,
233 // if polygon is extremly flat
234 for (i=0;i<arcsegs;i++)
236 cl = new QCanvasLine(canvas);
237 cl->setPen( QPen(linkcolor, 1) );
238 cl->setPoints( 0,0,i*10,100);
250 // FIXME updateLink is usually called (multiple times) later:
254 qWarning ("Error: ChildObj or parObj == NULL in LinkableMapObj::setLinkStyle\n");
258 LinkStyle LinkableMapObj::getLinkStyle()
263 void LinkableMapObj::setHideLinkUnselected(bool b)
265 hideLinkUnselected=b;
266 setVisibility (visible);
270 bool LinkableMapObj::getHideLinkUnselected()
272 return hideLinkUnselected;
275 void LinkableMapObj::setLinkPos(LinkPos lp)
280 LinkPos LinkableMapObj::getLinkPos()
286 void LinkableMapObj::setLinkColor()
288 // Overloaded in BranchObj and childs
289 // here only set default color
290 setLinkColor (mapEditor->getDefLinkColor());
293 void LinkableMapObj::setLinkColor(QColor col)
296 bottomline->setPen( QPen(linkcolor, 1) );
301 l->setPen( QPen(col,1));
304 for (cl=segment.first(); cl; cl=segment.next() )
305 cl->setPen( QPen(col,1));
308 p->setBrush( QBrush(col));
309 l->setPen( QPen(col,1));
311 case StylePolyParabel:
312 p->setBrush( QBrush(col));
313 for (cl=segment.first(); cl; cl=segment.next() )
314 cl->setPen( QPen(col,1));
321 QColor LinkableMapObj::getLinkColor()
326 FrameType LinkableMapObj::getFrameType()
328 return frame->getFrameType();
331 void LinkableMapObj::setFrameType(const FrameType &t)
333 frame->setFrameType(t);
339 void LinkableMapObj::setFrameType(const QString &t)
341 frame->setFrameType(t);
347 void LinkableMapObj::setVisibility (bool v)
350 MapObj::setVisibility (v);
352 if (hideLinkUnselected && !selected)
364 for (cl=segment.first(); cl; cl=segment.next() )
371 case StylePolyParabel:
372 for (cl=segment.first(); cl; cl=segment.next() )
388 for (cl=segment.first(); cl; cl=segment.next() )
395 case StylePolyParabel:
396 for (cl=segment.first(); cl; cl=segment.next() )
406 void LinkableMapObj::updateLink()
409 // childPos of parent
418 // drawing of the link itself
421 // updateLink is called from move, but called from constructor we don't
422 // have parents yet...
423 if (style==StyleUndef) return;
425 if (frame->getFrameType() == NoFrame)
432 offset=bbox.height() /2;
435 offset=bbox.height()-1; // draw link to bottom of bbox
439 double p2x,p2y; // Set P2 Before setting
442 p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at
443 p2y=QPoint( parObj->getChildPos() ).y(); // orientation
446 p2x=QPoint( parObj->getParPos() ).x();
447 p2y=QPoint( parObj->getParPos() ).y();
450 LinkOrient orientOld=orientation;
452 // Set orientation, first look for orientation of parent
453 if (parObj->getOrientation() != OrientUndef )
454 // use the orientation of the parent:
455 orientation=parObj->getOrientation();
458 // calc orientation depending on position rel to mapCenter
459 if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
460 orientation=OrientLeftOfCenter;
462 orientation=OrientRightOfCenter;
465 if ((orientation!=orientOld) && (orientOld!= OrientUndef))
467 // Orientation just changed. Reorient this subbranch, because move is called
468 // before updateLink => Position is still the old one, which could lead to
469 // linking of subranch to itself => segfault
471 // Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
472 // no need to reposition now
476 if (orientation==OrientLeftOfCenter )
478 childPos=QPoint (absPos.x(),absPos.y()+offset);
479 parPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset );
482 childPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset );
483 parPos=QPoint (absPos.x(),absPos.y()+offset);
486 double p1x=parPos.x(); // Link is drawn from P1 to P2
487 double p1y=parPos.y();
489 double vx=p2x - p1x; // V=P2-P1
492 // Draw the horizontal line below heading (from ChildPos to ParPos)
493 bottomline->setPoints (qRound(childPos.x()),
494 qRound(childPos.y()),
499 if (vx > -0.000001 && vx < 0.000001)
503 // "turning point" for drawing polygonal links
504 QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));
514 l->setPoints( qRound (parPos.x()),
520 parabel (pa0, p1x,p1y,p2x,p2y);
522 for (cl=segment.first(); cl; cl=segment.next() )
524 cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
529 pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
530 pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
531 pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
533 // here too, draw line to avoid missing pixels
534 l->setPoints( qRound (parPos.x()),
539 case StylePolyParabel:
540 parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
541 parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
542 for (i=0;i<=arcsegs;i++)
544 // Combine the arrays to a single one
546 pa0[i+arcsegs+1]=pa2[arcsegs-i];
550 for (cl=segment.first(); cl; cl=segment.next() )
552 cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
561 LinkableMapObj* LinkableMapObj::getChildObj()
566 LinkableMapObj* LinkableMapObj::getParObj()
571 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
573 LinkableMapObj *lmo=this;
577 while (!s.isEmpty() )
579 part=s.section(",",0,0);
581 num=part.right(part.length() - 3);
585 return false; // in a subtree there is no center
590 lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
593 lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
597 s=s.right(s.length() - part.length() -1 );
604 QPoint LinkableMapObj::getChildPos()
609 QPoint LinkableMapObj::getParPos()
614 QPoint LinkableMapObj::getRelPos()
616 if (!parObj) return QPoint (0,0);
618 absPos.x() - parObj->x(),
619 absPos.y() - parObj->y()
623 LinkOrient LinkableMapObj::getOrientation()
628 int LinkableMapObj::getDepth()
633 void LinkableMapObj::setMapEditor (MapEditor *me)
638 MapEditor* LinkableMapObj::getMapEditor ()
643 QPoint LinkableMapObj::getRandPos()
645 // Choose a random position with given distance to parent:
646 double a=rand()%360 * 2 * M_PI / 360;
647 return QPoint ( (int)( + 150*cos (a)),
648 (int)( + 150*sin (a)));
651 void LinkableMapObj::alignRelativeTo (QPoint ref)
653 cout << "LMO::alignRelTo ref="<<ref<<endl;
657 void LinkableMapObj::reposition()
661 // only calculate the sizes once. If the deepest LMO changes its height,
662 // all upper LMOs have to change, too.
663 calcBBoxSizeWithChilds();
665 alignRelativeTo ( QPoint (absPos.x(),
666 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
669 // This is only important for moving branches:
670 // For editing a branch it isn't called...
671 alignRelativeTo ( QPoint (absPos.x(),
672 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
676 void LinkableMapObj::requestReposition()
678 if (!repositionRequest)
680 // Pass on the request to parental objects, if this hasn't
682 repositionRequest=true;
683 if (parObj) parObj->requestReposition();
687 void LinkableMapObj::forceReposition()
689 // Sometimes a reposition has to be done immediatly: For example
690 // if the note editor flag changes, there is no user event in mapeditor
691 // which could collect requests for a reposition.
692 // Then we have to call forceReposition()
693 // But no rule without exception: While loading a map or undoing it,
694 // we want to block expensive repositioning, but just do it once at
695 // the end, thus check first:
697 if (mapEditor->isRepositionBlocked()) return;
699 // Pass on the request to parental objects, if this hasn't been done yet
702 parObj->forceReposition();
707 bool LinkableMapObj::repositionRequested()
709 return repositionRequest;
713 void LinkableMapObj::setSelBox()
715 selbox->setX (bbox.x() );
716 selbox->setY (bbox.y() );
717 selbox->setSize (bbox.width(), bbox.height() );
720 void LinkableMapObj::select()
725 setVisibility (visible);
729 void LinkableMapObj::unselect()
733 setVisibility (visible);
736 void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
739 double vx=p2x - p1x; // V=P2-P1
742 double dx; // delta x during calculation of parabel
744 double pnx; // next point
748 if (vx > -0.0001 && vx < 0.0001)
754 ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
755 for (i=1;i<=arcsegs;i++)
758 pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
759 ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
765 QString LinkableMapObj::getLinkAttr ()
768 if (hideLinkUnselected)
769 // Since this is currently the
770 // only attribut and it is switched off by default
771 // don't write <link> at all if it is missing
772 return attribut ("hideLinkUnselected","true");