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;
98 frame = new FrameObj (canvas);
100 repositionRequest=false;
103 void LinkableMapObj::copy (LinkableMapObj* other)
106 bboxTotal=other->bboxTotal;
107 setLinkStyle(other->style);
108 setLinkColor (other->linkcolor);
111 void LinkableMapObj::setChildObj(LinkableMapObj* o)
116 void LinkableMapObj::setParObj(LinkableMapObj* o)
119 mapEditor=parObj->getMapEditor();
122 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
126 void LinkableMapObj::unsetParObjTmp()
130 bool LinkableMapObj::hasParObjTmp()
132 if (parObjTmpBuf) return true;
136 LinkStyle LinkableMapObj::getDefLinkStyle ()
138 if (!mapEditor) return StyleUndef;
140 LinkStyle ls=mapEditor->getLinkStyle();
155 case StylePolyParabel:
167 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
169 //if (newstyle=style) return;
174 if (childObj!=NULL && parObj != NULL)
184 l = new QCanvasLine(canvas);
185 l->setPen( QPen(linkcolor, 1) );
193 for (i=0;i<arcsegs;i++)
195 cl = new QCanvasLine(canvas);
196 cl->setPen( QPen(linkcolor, 1) );
197 cl->setPoints( 0,0,i*10,100);
205 pa0.resize (arcsegs+1);
208 p = new QCanvasPolygon(canvas);
209 p->setBrush( linkcolor );
216 // TODO a bit awkward: draw the lines additionally to polygon, to avoid
217 // missing pixels, when polygon is extremly flat
218 l = new QCanvasLine(canvas);
219 l->setPen( QPen(linkcolor, 1) );
226 case StylePolyParabel:
227 p = new QCanvasPolygon(canvas);
228 p->setBrush( linkcolor );
234 pa0.resize (arcsegs*2+2);
235 pa1.resize (arcsegs+1);
236 pa2.resize (arcsegs+1);
238 // TODO a bit awkward: draw the lines additionally
239 // to polygon, to avoid missing pixels,
240 // if polygon is extremly flat
241 for (i=0;i<arcsegs;i++)
243 cl = new QCanvasLine(canvas);
244 cl->setPen( QPen(linkcolor, 1) );
245 cl->setPoints( 0,0,i*10,100);
260 LinkStyle LinkableMapObj::getLinkStyle()
265 void LinkableMapObj::setHideLinkUnselected(bool b)
267 hideLinkUnselected=b;
268 setVisibility (visible);
272 bool LinkableMapObj::getHideLinkUnselected()
274 return hideLinkUnselected;
277 void LinkableMapObj::setLinkPos(LinkPos lp)
282 LinkPos LinkableMapObj::getLinkPos()
288 void LinkableMapObj::setLinkColor()
290 // Overloaded in BranchObj and childs
291 // here only set default color
293 setLinkColor (mapEditor->getDefLinkColor());
296 void LinkableMapObj::setLinkColor(QColor col)
299 bottomline->setPen( QPen(linkcolor, 1) );
304 l->setPen( QPen(col,1));
307 for (cl=segment.first(); cl; cl=segment.next() )
308 cl->setPen( QPen(col,1));
311 p->setBrush( QBrush(col));
312 l->setPen( QPen(col,1));
314 case StylePolyParabel:
315 p->setBrush( QBrush(col));
316 for (cl=segment.first(); cl; cl=segment.next() )
317 cl->setPen( QPen(col,1));
324 QColor LinkableMapObj::getLinkColor()
329 FrameType LinkableMapObj::getFrameType()
331 return frame->getFrameType();
334 void LinkableMapObj::setFrameType(const FrameType &t)
336 frame->setFrameType(t);
342 void LinkableMapObj::setFrameType(const QString &t)
344 frame->setFrameType(t);
350 void LinkableMapObj::setVisibility (bool v)
353 MapObj::setVisibility (v);
355 if (hideLinkUnselected && !selected)
367 for (cl=segment.first(); cl; cl=segment.next() )
374 case StylePolyParabel:
375 for (cl=segment.first(); cl; cl=segment.next() )
391 for (cl=segment.first(); cl; cl=segment.next() )
398 case StylePolyParabel:
399 for (cl=segment.first(); cl; cl=segment.next() )
409 void LinkableMapObj::updateLink()
412 // childPos of parent
421 // drawing of the link itself
424 // updateLink is called from move, but called from constructor we don't
425 // have parents yet...
426 if (style==StyleUndef) return;
428 if (frame->getFrameType() == NoFrame)
435 offset=bbox.height() /2;
438 offset=bbox.height()-1; // draw link to bottom of bbox
442 double p2x,p2y; // Set P2 Before setting
445 p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at
446 p2y=QPoint( parObj->getChildPos() ).y(); // orientation
449 p2x=QPoint( parObj->getParPos() ).x();
450 p2y=QPoint( parObj->getParPos() ).y();
453 LinkOrient orientOld=orientation;
455 // Set orientation, first look for orientation of parent
456 if (parObj->getOrientation() != OrientUndef )
457 // use the orientation of the parent:
458 orientation=parObj->getOrientation();
461 // calc orientation depending on position rel to mapCenter
462 if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
463 orientation=OrientLeftOfCenter;
465 orientation=OrientRightOfCenter;
468 if ((orientation!=orientOld) && (orientOld!= OrientUndef))
470 // Orientation just changed. Reorient this subbranch, because move is called
471 // before updateLink => Position is still the old one, which could lead to
472 // linking of subranch to itself => segfault
474 // Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
475 // no need to reposition now
479 if (orientation==OrientLeftOfCenter )
481 childPos=QPoint (absPos.x(),absPos.y()+offset);
482 parPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset );
485 childPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset );
486 parPos=QPoint (absPos.x(),absPos.y()+offset);
489 double p1x=parPos.x(); // Link is drawn from P1 to P2
490 double p1y=parPos.y();
492 double vx=p2x - p1x; // V=P2-P1
495 // Draw the horizontal line below heading (from ChildPos to ParPos)
496 bottomline->setPoints (qRound(childPos.x()),
497 qRound(childPos.y()),
502 if (vx > -0.000001 && vx < 0.000001)
506 // "turning point" for drawing polygonal links
507 QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));
517 l->setPoints( qRound (parPos.x()),
523 parabel (pa0, p1x,p1y,p2x,p2y);
525 for (cl=segment.first(); cl; cl=segment.next() )
527 cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
532 pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
533 pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
534 pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
536 // here too, draw line to avoid missing pixels
537 l->setPoints( qRound (parPos.x()),
542 case StylePolyParabel:
543 parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
544 parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
545 for (i=0;i<=arcsegs;i++)
547 // Combine the arrays to a single one
549 pa0[i+arcsegs+1]=pa2[arcsegs-i];
553 for (cl=segment.first(); cl; cl=segment.next() )
555 cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
564 LinkableMapObj* LinkableMapObj::getChildObj()
569 LinkableMapObj* LinkableMapObj::getParObj()
574 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
576 LinkableMapObj *lmo=this;
580 while (!s.isEmpty() )
582 part=s.section(",",0,0);
584 num=part.right(part.length() - 3);
588 return false; // in a subtree there is no center
593 lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
596 lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
600 s=s.right(s.length() - part.length() -1 );
607 QPoint LinkableMapObj::getChildPos()
612 QPoint LinkableMapObj::getParPos()
617 QPoint LinkableMapObj::getRelPos()
619 if (!parObj) return QPoint (0,0);
621 absPos.x() - parObj->x(),
622 absPos.y() - parObj->y()
626 LinkOrient LinkableMapObj::getOrientation()
631 int LinkableMapObj::getDepth()
636 void LinkableMapObj::setMapEditor (MapEditor *me)
641 MapEditor* LinkableMapObj::getMapEditor ()
646 QPoint LinkableMapObj::getRandPos()
648 // Choose a random position with given distance to parent:
649 double a=rand()%360 * 2 * M_PI / 360;
650 return QPoint ( (int)( + 150*cos (a)),
651 (int)( + 150*sin (a)));
654 void LinkableMapObj::alignRelativeTo (QPoint ref)
656 // FIXME testing, seems not to be used right now...
657 cout << "LMO::alignRelTo ref="<<ref<<endl;
660 void LinkableMapObj::reposition()
664 // only calculate the sizes once. If the deepest LMO changes its height,
665 // all upper LMOs have to change, too.
666 calcBBoxSizeWithChilds();
668 alignRelativeTo ( QPoint (absPos.x(),
669 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
672 // This is only important for moving branches:
673 // For editing a branch it isn't called...
674 alignRelativeTo ( QPoint (absPos.x(),
675 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
679 void LinkableMapObj::requestReposition()
681 if (!repositionRequest)
683 // Pass on the request to parental objects, if this hasn't
685 repositionRequest=true;
686 if (parObj) parObj->requestReposition();
690 void LinkableMapObj::forceReposition()
692 // Sometimes a reposition has to be done immediatly: For example
693 // if the note editor flag changes, there is no user event in mapeditor
694 // which could collect requests for a reposition.
695 // Then we have to call forceReposition()
696 // But no rule without exception: While loading a map or undoing it,
697 // we want to block expensive repositioning, but just do it once at
698 // the end, thus check first:
700 if (mapEditor->isRepositionBlocked()) return;
702 // Pass on the request to parental objects, if this hasn't been done yet
705 parObj->forceReposition();
710 bool LinkableMapObj::repositionRequested()
712 return repositionRequest;
716 void LinkableMapObj::setSelBox()
718 selbox->setX (bbox.x() );
719 selbox->setY (bbox.y() );
720 selbox->setSize (bbox.width(), bbox.height() );
723 void LinkableMapObj::select()
728 setVisibility (visible);
732 void LinkableMapObj::unselect()
736 setVisibility (visible);
739 void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
742 double vx=p2x - p1x; // V=P2-P1
745 double dx; // delta x during calculation of parabel
747 double pnx; // next point
751 if (vx > -0.0001 && vx < 0.0001)
757 ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
758 for (i=1;i<=arcsegs;i++)
761 pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
762 ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
768 QString LinkableMapObj::getLinkAttr ()
771 if (hideLinkUnselected)
772 // Since this is currently the
773 // only attribut and it is switched off by default
774 // don't write <link> at all if it is missing
775 return attribut ("hideLinkUnselected","true");