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;
105 void LinkableMapObj::copy (LinkableMapObj* other)
108 bboxTotal=other->bboxTotal;
109 setLinkStyle(other->style);
110 setLinkColor (other->linkcolor);
113 void LinkableMapObj::setChildObj(LinkableMapObj* o)
118 void LinkableMapObj::setParObj(LinkableMapObj* o)
121 mapEditor=parObj->getMapEditor();
124 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
128 void LinkableMapObj::unsetParObjTmp()
132 bool LinkableMapObj::hasParObjTmp()
134 if (parObjTmpBuf) return true;
138 int LinkableMapObj::getTopPad()
143 int LinkableMapObj::getLeftPad()
148 int LinkableMapObj::getRightPad()
153 LinkStyle LinkableMapObj::getDefLinkStyle ()
155 if (!mapEditor) return StyleUndef;
157 LinkStyle ls=mapEditor->getLinkStyle();
172 case StylePolyParabel:
184 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
186 //if (newstyle=style) return;
191 if (childObj!=NULL && parObj != NULL)
201 l = new QCanvasLine(canvas);
202 l->setPen( QPen(linkcolor, 1) );
210 for (i=0;i<arcsegs;i++)
212 cl = new QCanvasLine(canvas);
213 cl->setPen( QPen(linkcolor, 1) );
214 cl->setPoints( 0,0,i*10,100);
222 pa0.resize (arcsegs+1);
225 p = new QCanvasPolygon(canvas);
226 p->setBrush( linkcolor );
233 // TODO a bit awkward: draw the lines additionally to polygon, to avoid
234 // missing pixels, when polygon is extremly flat
235 l = new QCanvasLine(canvas);
236 l->setPen( QPen(linkcolor, 1) );
243 case StylePolyParabel:
244 p = new QCanvasPolygon(canvas);
245 p->setBrush( linkcolor );
251 pa0.resize (arcsegs*2+2);
252 pa1.resize (arcsegs+1);
253 pa2.resize (arcsegs+1);
255 // TODO a bit awkward: draw the lines additionally
256 // to polygon, to avoid missing pixels,
257 // if polygon is extremly flat
258 for (i=0;i<arcsegs;i++)
260 cl = new QCanvasLine(canvas);
261 cl->setPen( QPen(linkcolor, 1) );
262 cl->setPoints( 0,0,i*10,100);
277 LinkStyle LinkableMapObj::getLinkStyle()
282 void LinkableMapObj::setHideLinkUnselected(bool b)
284 hideLinkUnselected=b;
285 setVisibility (visible);
289 bool LinkableMapObj::getHideLinkUnselected()
291 return hideLinkUnselected;
294 void LinkableMapObj::setLinkPos(LinkPos lp)
299 LinkPos LinkableMapObj::getLinkPos()
305 void LinkableMapObj::setLinkColor()
307 // Overloaded in BranchObj and childs
308 // here only set default color
310 setLinkColor (mapEditor->getDefLinkColor());
313 void LinkableMapObj::setLinkColor(QColor col)
316 bottomline->setPen( QPen(linkcolor, 1) );
321 l->setPen( QPen(col,1));
324 for (cl=segment.first(); cl; cl=segment.next() )
325 cl->setPen( QPen(col,1));
328 p->setBrush( QBrush(col));
329 l->setPen( QPen(col,1));
331 case StylePolyParabel:
332 p->setBrush( QBrush(col));
333 for (cl=segment.first(); cl; cl=segment.next() )
334 cl->setPen( QPen(col,1));
341 QColor LinkableMapObj::getLinkColor()
346 FrameType LinkableMapObj::getFrameType()
348 return frame->getFrameType();
351 void LinkableMapObj::setFrameType(const FrameType &t)
353 frame->setFrameType(t);
359 void LinkableMapObj::setFrameType(const QString &t)
361 frame->setFrameType(t);
367 void LinkableMapObj::setVisibility (bool v)
370 MapObj::setVisibility (v);
372 if (hideLinkUnselected && !selected)
384 for (cl=segment.first(); cl; cl=segment.next() )
391 case StylePolyParabel:
392 for (cl=segment.first(); cl; cl=segment.next() )
408 for (cl=segment.first(); cl; cl=segment.next() )
415 case StylePolyParabel:
416 for (cl=segment.first(); cl; cl=segment.next() )
426 void LinkableMapObj::updateLink()
429 // childPos of parent
438 // drawing of the link itself
441 // updateLink is called from move, but called from constructor we don't
442 // have parents yet...
443 if (style==StyleUndef) return;
445 if (frame->getFrameType() == NoFrame)
452 bottomlineY=clickBox.top()+clickBox.height() /2; // draw link to middle (of frame)
455 bottomlineY=clickBox.bottom()-1; // draw link to bottom of bbox
459 double p2x,p2y; // Set P2 Before setting
462 p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at
463 p2y=QPoint( parObj->getChildPos() ).y(); // orientation
466 p2x=QPoint( parObj->getParPos() ).x();
467 p2y=QPoint( parObj->getParPos() ).y();
470 LinkOrient orientOld=orientation;
472 // Set orientation, first look for orientation of parent
473 if (parObj->getOrientation() != OrientUndef )
474 // use the orientation of the parent:
475 orientation=parObj->getOrientation();
478 // calc orientation depending on position rel to mapCenter
479 if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
480 orientation=OrientLeftOfCenter;
482 orientation=OrientRightOfCenter;
485 if ((orientation!=orientOld) && (orientOld!= OrientUndef))
487 // Orientation just changed. Reorient this subbranch, because move is called
488 // before updateLink => Position is still the old one, which could lead to
489 // linking of subranch to itself => segfault
491 // Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
492 // no need to reposition now
496 if (orientation==OrientLeftOfCenter )
498 childPos=QPoint (absPos.x(),bottomlineY);
499 parPos=QPoint (absPos.x()+ bbox.width(), bottomlineY );
502 childPos=QPoint (absPos.x()+ bbox.width(), bottomlineY );
503 parPos=QPoint (absPos.x(),bottomlineY);
506 double p1x=parPos.x(); // Link is drawn from P1 to P2
507 double p1y=parPos.y();
509 double vx=p2x - p1x; // V=P2-P1
512 // Draw the horizontal line below heading (from ChildPos to ParPos)
513 bottomline->setPoints (qRound(childPos.x()),
514 qRound(childPos.y()),
519 if (vx > -0.000001 && vx < 0.000001)
523 // "turning point" for drawing polygonal links
524 QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));
534 l->setPoints( qRound (parPos.x()),
540 parabel (pa0, p1x,p1y,p2x,p2y);
542 for (cl=segment.first(); cl; cl=segment.next() )
544 cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
549 pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
550 pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
551 pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
553 // here too, draw line to avoid missing pixels
554 l->setPoints( qRound (parPos.x()),
559 case StylePolyParabel:
560 parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
561 parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
562 for (i=0;i<=arcsegs;i++)
564 // Combine the arrays to a single one
566 pa0[i+arcsegs+1]=pa2[arcsegs-i];
570 for (cl=segment.first(); cl; cl=segment.next() )
572 cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
581 LinkableMapObj* LinkableMapObj::getChildObj()
586 LinkableMapObj* LinkableMapObj::getParObj()
591 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
593 LinkableMapObj *lmo=this;
597 while (!s.isEmpty() )
599 part=s.section(",",0,0);
601 num=part.right(part.length() - 3);
605 return false; // in a subtree there is no center
610 lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
613 lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
617 s=s.right(s.length() - part.length() -1 );
624 QPoint LinkableMapObj::getChildPos()
629 QPoint LinkableMapObj::getParPos()
634 QPoint LinkableMapObj::getRelPos()
636 if (!parObj) return QPoint (0,0);
638 absPos.x() - parObj->x(),
639 absPos.y() - parObj->y()
643 LinkOrient LinkableMapObj::getOrientation()
648 int LinkableMapObj::getDepth()
653 void LinkableMapObj::setMapEditor (MapEditor *me)
658 MapEditor* LinkableMapObj::getMapEditor ()
663 QPoint LinkableMapObj::getRandPos()
665 // Choose a random position with given distance to parent:
666 double a=rand()%360 * 2 * M_PI / 360;
667 return QPoint ( (int)( + 150*cos (a)),
668 (int)( + 150*sin (a)));
671 void LinkableMapObj::alignRelativeTo (QPoint ref)
673 // FIXME testing, seems not to be used right now...
674 cout << "LMO::alignRelTo ref="<<ref<<endl;
677 void LinkableMapObj::reposition()
681 // only calculate the sizes once. If the deepest LMO changes its height,
682 // all upper LMOs have to change, too.
683 calcBBoxSizeWithChilds();
685 alignRelativeTo ( QPoint (absPos.x(),
686 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
689 // This is only important for moving branches:
690 // For editing a branch it isn't called...
691 alignRelativeTo ( QPoint (absPos.x(),
692 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
696 void LinkableMapObj::requestReposition()
698 if (!repositionRequest)
700 // Pass on the request to parental objects, if this hasn't
702 repositionRequest=true;
703 if (parObj) parObj->requestReposition();
707 void LinkableMapObj::forceReposition()
709 // Sometimes a reposition has to be done immediatly: For example
710 // if the note editor flag changes, there is no user event in mapeditor
711 // which could collect requests for a reposition.
712 // Then we have to call forceReposition()
713 // But no rule without exception: While loading a map or undoing it,
714 // we want to block expensive repositioning, but just do it once at
715 // the end, thus check first:
717 if (mapEditor->isRepositionBlocked()) return;
719 // Pass on the request to parental objects, if this hasn't been done yet
722 parObj->forceReposition();
727 bool LinkableMapObj::repositionRequested()
729 return repositionRequest;
733 void LinkableMapObj::setSelBox()
735 selbox->setX (clickBox.x() );
736 selbox->setY (clickBox.y() );
737 selbox->setSize (clickBox.width(), clickBox.height() );
740 void LinkableMapObj::select()
745 setVisibility (visible);
749 void LinkableMapObj::unselect()
753 setVisibility (visible);
756 void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
759 double vx=p2x - p1x; // V=P2-P1
762 double dx; // delta x during calculation of parabel
764 double pnx; // next point
768 if (vx > -0.0001 && vx < 0.0001)
774 ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
775 for (i=1;i<=arcsegs;i++)
778 pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
779 ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
785 QString LinkableMapObj::getLinkAttr ()
787 if (hideLinkUnselected)
788 return attribut ("hideLink","true");
790 return attribut ("hideLink","false");