historywindow moved to mainwindow. Started to get rid of Q3PtrList finally
3 #include "linkablemapobj.h"
8 #include <Q3PointArray>
11 /////////////////////////////////////////////////////////////////
13 /////////////////////////////////////////////////////////////////
15 LinkableMapObj::LinkableMapObj():MapObj()
17 // cout << "Const LinkableMapObj ()\n";
21 LinkableMapObj::LinkableMapObj(Q3Canvas* c) :MapObj(c)
23 // cout << "Const LinkableMapObj\n";
27 LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
32 LinkableMapObj::~LinkableMapObj()
40 void LinkableMapObj::delLink()
54 case StylePolyParabel:
63 void LinkableMapObj::init ()
74 orientation=OrientUndef;
79 segment.setAutoDelete (TRUE);
81 Q3PointArray pa(arcsegs*2+2);
83 bottomline=new Q3CanvasLine(canvas);
84 bottomline->setPen( QPen(linkcolor, 1) );
85 bottomline->setZ(Z_LINK);
88 // Prepare showing the selection of a MapObj
89 selbox = new Q3CanvasRectangle (canvas);
90 selbox->setZ(Z_SELBOX);
91 selbox->setBrush( QColor(255,255,0) );
92 selbox->setPen( QPen(QColor(255,255,0) ));
96 hideLinkUnselected=false;
98 topPad=botPad=leftPad=rightPad=0;
101 frame = new FrameObj (canvas);
103 repositionRequest=false;
111 void LinkableMapObj::copy (LinkableMapObj* other)
114 bboxTotal=other->bboxTotal;
115 setLinkStyle(other->style);
116 setLinkColor (other->linkcolor);
117 relPos=other->relPos;
118 useOrientation=other->useOrientation;
122 void LinkableMapObj::setChildObj(LinkableMapObj* o)
127 void LinkableMapObj::setParObj(LinkableMapObj* o)
130 mapEditor=parObj->getMapEditor();
133 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
137 void LinkableMapObj::unsetParObjTmp()
141 bool LinkableMapObj::hasParObjTmp()
143 if (parObjTmpBuf) return true;
147 void LinkableMapObj::setUseRelPos (const bool &b)
152 void LinkableMapObj::setRelPos()
156 relPos.setX (absPos.x() - parObj->getChildPos().x() );
157 relPos.setY (absPos.y() - parObj->getChildPos().y() );
158 parObj->calcBBoxSize();
161 qWarning ("LMO::setRelPos No parent yet!");
165 void LinkableMapObj::setRelPos(const QPoint &p)
170 parObj->calcBBoxSize();
174 qWarning ("LMO::setRelPos No parent yet!");
178 QPoint LinkableMapObj::getRelPos()
180 if (!parObj) return QPoint();
184 int LinkableMapObj::getTopPad()
189 int LinkableMapObj::getLeftPad()
194 int LinkableMapObj::getRightPad()
199 LinkStyle LinkableMapObj::getDefLinkStyle ()
201 if (!mapEditor) return StyleUndef;
203 LinkStyle ls=mapEditor->getMapLinkStyle();
218 case StylePolyParabel:
230 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
232 //if (newstyle=style) return;
237 if (childObj!=NULL && parObj != NULL)
247 l = new Q3CanvasLine(canvas);
248 l->setPen( QPen(linkcolor, 1) );
256 for (i=0;i<arcsegs;i++)
258 cl = new Q3CanvasLine(canvas);
259 cl->setPen( QPen(linkcolor, 1) );
260 cl->setPoints( 0,0,i*10,100);
268 pa0.resize (arcsegs+1);
271 p = new Q3CanvasPolygon(canvas);
272 p->setBrush( linkcolor );
279 // TODO a bit awkward: draw the lines additionally to polygon, to avoid
280 // missing pixels, when polygon is extremly flat
281 l = new Q3CanvasLine(canvas);
282 l->setPen( QPen(linkcolor, 1) );
289 case StylePolyParabel:
290 p = new Q3CanvasPolygon(canvas);
291 p->setBrush( linkcolor );
297 pa0.resize (arcsegs*2+2);
298 pa1.resize (arcsegs+1);
299 pa2.resize (arcsegs+1);
301 // TODO a bit awkward: draw the lines additionally
302 // to polygon, to avoid missing pixels,
303 // if polygon is extremly flat
304 for (i=0;i<arcsegs;i++)
306 cl = new Q3CanvasLine(canvas);
307 cl->setPen( QPen(linkcolor, 1) );
308 cl->setPoints( 0,0,i*10,100);
323 LinkStyle LinkableMapObj::getLinkStyle()
328 void LinkableMapObj::setHideLinkUnselected(bool b)
330 hideLinkUnselected=b;
331 setVisibility (visible);
335 bool LinkableMapObj::getHideLinkUnselected()
337 return hideLinkUnselected;
340 void LinkableMapObj::setLinkPos(LinkPos lp)
345 LinkPos LinkableMapObj::getLinkPos()
351 void LinkableMapObj::setLinkColor()
353 // Overloaded in BranchObj and childs
354 // here only set default color
356 setLinkColor (mapEditor->getMapDefLinkColor());
359 void LinkableMapObj::setLinkColor(QColor col)
362 bottomline->setPen( QPen(linkcolor, 1) );
367 l->setPen( QPen(col,1));
370 for (cl=segment.first(); cl; cl=segment.next() )
371 cl->setPen( QPen(col,1));
374 p->setBrush( QBrush(col));
375 l->setPen( QPen(col,1));
377 case StylePolyParabel:
378 p->setBrush( QBrush(col));
379 for (cl=segment.first(); cl; cl=segment.next() )
380 cl->setPen( QPen(col,1));
387 QColor LinkableMapObj::getLinkColor()
392 FrameType LinkableMapObj::getFrameType()
394 return frame->getFrameType();
397 void LinkableMapObj::setFrameType(const FrameType &t)
399 frame->setFrameType(t);
405 void LinkableMapObj::setFrameType(const QString &t)
407 frame->setFrameType(t);
413 void LinkableMapObj::setVisibility (bool v)
416 MapObj::setVisibility (v);
419 // We can hide the link, while object is not selected
420 if (hideLinkUnselected && !selected)
432 for (cl=segment.first(); cl; cl=segment.next() )
439 case StylePolyParabel:
440 for (cl=segment.first(); cl; cl=segment.next() )
456 for (cl=segment.first(); cl; cl=segment.next() )
463 case StylePolyParabel:
464 for (cl=segment.first(); cl; cl=segment.next() )
474 void LinkableMapObj::setOrientation()
476 LinkOrient orientOld=orientation;
480 orientation=OrientUndef;
484 // Set orientation, first look for orientation of parent
485 if (parObj->getOrientation() != OrientUndef )
486 // use the orientation of the parent:
487 orientation=parObj->getOrientation();
490 // calc orientation depending on position rel to parent
491 if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
492 orientation=OrientLeftOfCenter;
494 orientation=OrientRightOfCenter;
496 if (orientOld!=orientation) requestReposition();
499 void LinkableMapObj::updateLink()
502 // childPos of parent
508 // childPos (by calling setDockPos())
509 // parPos (by calling setDockPos())
511 // drawing of the link itself
513 // updateLink is called from move, but called from constructor we don't
514 // have parents yet...
515 if (style==StyleUndef) return;
517 if (frame->getFrameType() == NoFrame)
524 bottomlineY=bbox.top()+bbox.height() /2; // draw link to middle (of frame)
527 bottomlineY=bbox.bottom()-1; // draw link to bottom of box
531 double p2x,p2y; // Set P2 Before setting
534 p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at
535 p2y=QPoint( parObj->getChildPos() ).y(); // orientation
538 p2x=QPoint( parObj->getParPos() ).x();
539 p2y=QPoint( parObj->getParPos() ).y();
542 setDockPos(); // Call overloaded method
545 double p1x=parPos.x(); // Link is drawn from P1 to P2
546 double p1y=parPos.y();
548 double vx=p2x - p1x; // V=P2-P1
551 // Draw the horizontal line below heading (from ChildPos to ParPos)
552 bottomline->setPoints (qRound(childPos.x()),
553 qRound(childPos.y()),
558 if (vx > -0.000001 && vx < 0.000001)
562 // "turning point" for drawing polygonal links
563 QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));
573 l->setPoints( qRound (parPos.x()),
579 parabel (pa0, p1x,p1y,p2x,p2y);
581 for (cl=segment.first(); cl; cl=segment.next() )
583 cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
588 pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
589 pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
590 pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
592 // here too, draw line to avoid missing pixels
593 l->setPoints( qRound (parPos.x()),
598 case StylePolyParabel:
599 parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
600 parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
601 for (i=0;i<=arcsegs;i++)
603 // Combine the arrays to a single one
605 pa0[i+arcsegs+1]=pa2[arcsegs-i];
609 for (cl=segment.first(); cl; cl=segment.next() )
611 cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
620 LinkableMapObj* LinkableMapObj::getChildObj()
625 LinkableMapObj* LinkableMapObj::getParObj()
630 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
632 LinkableMapObj *lmo=this;
636 while (!s.isEmpty() )
638 part=s.section(",",0,0);
640 num=part.right(part.length() - 3);
644 return false; // in a subtree there is no center
649 lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
652 lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
656 s=s.right(s.length() - part.length() -1 );
663 QPoint LinkableMapObj::getChildPos()
668 QPoint LinkableMapObj::getParPos()
673 void LinkableMapObj::setUseOrientation (const bool &b)
675 if (useOrientation!=b)
682 LinkOrient LinkableMapObj::getOrientation()
687 int LinkableMapObj::getDepth()
692 void LinkableMapObj::setMapEditor (MapEditor *me)
697 MapEditor* LinkableMapObj::getMapEditor ()
702 QPoint LinkableMapObj::getRandPos()
704 // Choose a random position with given distance to parent:
705 double a=rand()%360 * 2 * M_PI / 360;
706 return QPoint ( (int)( + 150*cos (a)),
707 (int)( + 150*sin (a)));
711 void LinkableMapObj::alignRelativeTo (QPoint ref)
713 // Overloaded, only called for BO, FIO, ...
718 void LinkableMapObj::reposition()
720 cout << "LMO::reposition\n";
721 // FIXME not needed? Is overloaded in BranchObj...
725 // only calculate the sizes once. If the deepest LMO changes its height,
726 // all upper LMOs have to change, too.
727 calcBBoxSizeWithChilds();
729 alignRelativeTo ( QPoint (absPos.x(),
730 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
733 // This is only important for moving branches:
734 // For editing a branch it isn't called...
735 cout << " reposition to abs "<<absPos<<endl;
736 alignRelativeTo ( QPoint (absPos.x(),
737 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
742 void LinkableMapObj::requestReposition()
744 if (!repositionRequest)
746 // Pass on the request to parental objects, if this hasn't
748 repositionRequest=true;
749 if (parObj) parObj->requestReposition();
753 void LinkableMapObj::forceReposition()
755 // Sometimes a reposition has to be done immediatly: For example
756 // if the note editor flag changes, there is no user event in mapeditor
757 // which could collect requests for a reposition.
758 // Then we have to call forceReposition()
759 // But no rule without exception: While loading a map or undoing it,
760 // we want to block expensive repositioning, but just do it once at
761 // the end, thus check first:
763 if (mapEditor->isRepositionBlocked()) return;
765 // Pass on the request to parental objects, if this hasn't been done yet
768 parObj->forceReposition();
773 bool LinkableMapObj::repositionRequested()
775 return repositionRequest;
779 void LinkableMapObj::setSelBox()
781 selbox->setX (clickBox.x() );
782 selbox->setY (clickBox.y() );
783 selbox->setSize (clickBox.width(), clickBox.height() );
786 void LinkableMapObj::select()
792 setVisibility (visible);
796 void LinkableMapObj::unselect()
800 // Maybe we have to hide the link:
801 setVisibility (visible);
804 void LinkableMapObj::parabel (Q3PointArray &ya, double p1x, double p1y, double p2x, double p2y)
807 double vx=p2x - p1x; // V=P2-P1
810 double dx; // delta x during calculation of parabel
812 double pnx; // next point
816 if (vx > -0.0001 && vx < 0.0001)
822 ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
823 for (i=1;i<=arcsegs;i++)
826 pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
827 ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
833 QString LinkableMapObj::getLinkAttr ()
835 if (hideLinkUnselected)
836 return attribut ("hideLink","true");
838 return attribut ("hideLink","false");