More undo/redo commands. Undo debug output still enabled
3 #include "linkablemapobj.h"
9 #include <Q3PointArray>
12 /////////////////////////////////////////////////////////////////
14 /////////////////////////////////////////////////////////////////
16 LinkableMapObj::LinkableMapObj():MapObj()
18 // cout << "Const LinkableMapObj ()\n";
22 LinkableMapObj::LinkableMapObj(Q3Canvas* c) :MapObj(c)
24 // cout << "Const LinkableMapObj\n";
28 LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
33 LinkableMapObj::~LinkableMapObj()
41 void LinkableMapObj::delLink()
55 case StylePolyParabel:
64 void LinkableMapObj::init ()
75 orientation=OrientUndef;
80 segment.setAutoDelete (TRUE);
82 Q3PointArray pa(arcsegs*2+2);
84 bottomline=new Q3CanvasLine(canvas);
85 bottomline->setPen( QPen(linkcolor, 1) );
86 bottomline->setZ(Z_LINK);
89 // Prepare showing the selection of a MapObj
90 selbox = new Q3CanvasRectangle (canvas);
91 selbox->setZ(Z_SELBOX);
92 selbox->setBrush( QColor(255,255,0) );
93 selbox->setPen( QPen(QColor(255,255,0) ));
97 hideLinkUnselected=false;
99 topPad=botPad=leftPad=rightPad=0;
102 frame = new FrameObj (canvas);
104 repositionRequest=false;
112 void LinkableMapObj::copy (LinkableMapObj* other)
115 bboxTotal=other->bboxTotal;
116 setLinkStyle(other->style);
117 setLinkColor (other->linkcolor);
118 relPos=other->relPos;
119 useOrientation=other->useOrientation;
123 void LinkableMapObj::setChildObj(LinkableMapObj* o)
128 void LinkableMapObj::setParObj(LinkableMapObj* o)
131 mapEditor=parObj->getMapEditor();
134 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
138 void LinkableMapObj::unsetParObjTmp()
142 bool LinkableMapObj::hasParObjTmp()
144 if (parObjTmpBuf) return true;
148 void LinkableMapObj::setUseRelPos (const bool &b)
153 void LinkableMapObj::setRelPos()
157 relPos.setX (absPos.x() - parObj->getChildPos().x() );
158 relPos.setY (absPos.y() - parObj->getChildPos().y() );
160 parObj->calcBBoxSize();
161 parObj->requestReposition();
165 void LinkableMapObj::setRelPos(const QPoint &p)
169 { parObj->calcBBoxSize();
170 parObj->requestReposition();
174 int LinkableMapObj::getTopPad()
179 int LinkableMapObj::getLeftPad()
184 int LinkableMapObj::getRightPad()
189 LinkStyle LinkableMapObj::getDefLinkStyle ()
191 if (!mapEditor) return StyleUndef;
193 LinkStyle ls=mapEditor->getLinkStyle();
208 case StylePolyParabel:
220 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
222 //if (newstyle=style) return;
227 if (childObj!=NULL && parObj != NULL)
237 l = new Q3CanvasLine(canvas);
238 l->setPen( QPen(linkcolor, 1) );
246 for (i=0;i<arcsegs;i++)
248 cl = new Q3CanvasLine(canvas);
249 cl->setPen( QPen(linkcolor, 1) );
250 cl->setPoints( 0,0,i*10,100);
258 pa0.resize (arcsegs+1);
261 p = new Q3CanvasPolygon(canvas);
262 p->setBrush( linkcolor );
269 // TODO a bit awkward: draw the lines additionally to polygon, to avoid
270 // missing pixels, when polygon is extremly flat
271 l = new Q3CanvasLine(canvas);
272 l->setPen( QPen(linkcolor, 1) );
279 case StylePolyParabel:
280 p = new Q3CanvasPolygon(canvas);
281 p->setBrush( linkcolor );
287 pa0.resize (arcsegs*2+2);
288 pa1.resize (arcsegs+1);
289 pa2.resize (arcsegs+1);
291 // TODO a bit awkward: draw the lines additionally
292 // to polygon, to avoid missing pixels,
293 // if polygon is extremly flat
294 for (i=0;i<arcsegs;i++)
296 cl = new Q3CanvasLine(canvas);
297 cl->setPen( QPen(linkcolor, 1) );
298 cl->setPoints( 0,0,i*10,100);
313 LinkStyle LinkableMapObj::getLinkStyle()
318 void LinkableMapObj::setHideLinkUnselected(bool b)
320 hideLinkUnselected=b;
321 setVisibility (visible);
325 bool LinkableMapObj::getHideLinkUnselected()
327 return hideLinkUnselected;
330 void LinkableMapObj::setLinkPos(LinkPos lp)
335 LinkPos LinkableMapObj::getLinkPos()
341 void LinkableMapObj::setLinkColor()
343 // Overloaded in BranchObj and childs
344 // here only set default color
346 setLinkColor (mapEditor->getDefLinkColor());
349 void LinkableMapObj::setLinkColor(QColor col)
352 bottomline->setPen( QPen(linkcolor, 1) );
357 l->setPen( QPen(col,1));
360 for (cl=segment.first(); cl; cl=segment.next() )
361 cl->setPen( QPen(col,1));
364 p->setBrush( QBrush(col));
365 l->setPen( QPen(col,1));
367 case StylePolyParabel:
368 p->setBrush( QBrush(col));
369 for (cl=segment.first(); cl; cl=segment.next() )
370 cl->setPen( QPen(col,1));
377 QColor LinkableMapObj::getLinkColor()
382 FrameType LinkableMapObj::getFrameType()
384 return frame->getFrameType();
387 void LinkableMapObj::setFrameType(const FrameType &t)
389 frame->setFrameType(t);
395 void LinkableMapObj::setFrameType(const QString &t)
397 frame->setFrameType(t);
403 void LinkableMapObj::setVisibility (bool v)
406 MapObj::setVisibility (v);
409 // We can hide the link, while object is not selected
410 if (hideLinkUnselected && !selected)
422 for (cl=segment.first(); cl; cl=segment.next() )
429 case StylePolyParabel:
430 for (cl=segment.first(); cl; cl=segment.next() )
446 for (cl=segment.first(); cl; cl=segment.next() )
453 case StylePolyParabel:
454 for (cl=segment.first(); cl; cl=segment.next() )
464 void LinkableMapObj::updateLink()
467 // childPos of parent
473 // childPos (by calling setDockPos())
474 // parPos (by calling setDockPos())
476 // drawing of the link itself
478 // updateLink is called from move, but called from constructor we don't
479 // have parents yet...
480 if (style==StyleUndef) return;
482 if (frame->getFrameType() == NoFrame)
489 bottomlineY=bbox.top()+bbox.height() /2; // draw link to middle (of frame)
492 bottomlineY=bbox.bottom()-1; // draw link to bottom of box
496 double p2x,p2y; // Set P2 Before setting
499 p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at
500 p2y=QPoint( parObj->getChildPos() ).y(); // orientation
503 p2x=QPoint( parObj->getParPos() ).x();
504 p2y=QPoint( parObj->getParPos() ).y();
507 LinkOrient orientOld=orientation;
509 // Set orientation, first look for orientation of parent
510 if (parObj->getOrientation() != OrientUndef )
511 // use the orientation of the parent:
512 orientation=parObj->getOrientation();
515 // calc orientation depending on position rel to mapCenter
516 if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
517 orientation=OrientLeftOfCenter;
519 orientation=OrientRightOfCenter;
522 if ((orientation!=orientOld) && (orientOld!= OrientUndef))
524 // Orientation just changed. Reorient this subbranch, because move is called
525 // before updateLink => Position is still the old one, which could lead to
526 // linking of subranch to itself => segfault
528 // Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
529 // no need to reposition now
535 double p1x=parPos.x(); // Link is drawn from P1 to P2
536 double p1y=parPos.y();
538 double vx=p2x - p1x; // V=P2-P1
541 // Draw the horizontal line below heading (from ChildPos to ParPos)
542 bottomline->setPoints (qRound(childPos.x()),
543 qRound(childPos.y()),
548 if (vx > -0.000001 && vx < 0.000001)
552 // "turning point" for drawing polygonal links
553 QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));
563 l->setPoints( qRound (parPos.x()),
569 parabel (pa0, p1x,p1y,p2x,p2y);
571 for (cl=segment.first(); cl; cl=segment.next() )
573 cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
578 pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
579 pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
580 pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
582 // here too, draw line to avoid missing pixels
583 l->setPoints( qRound (parPos.x()),
588 case StylePolyParabel:
589 parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
590 parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
591 for (i=0;i<=arcsegs;i++)
593 // Combine the arrays to a single one
595 pa0[i+arcsegs+1]=pa2[arcsegs-i];
599 for (cl=segment.first(); cl; cl=segment.next() )
601 cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
610 LinkableMapObj* LinkableMapObj::getChildObj()
615 LinkableMapObj* LinkableMapObj::getParObj()
620 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
622 LinkableMapObj *lmo=this;
626 while (!s.isEmpty() )
628 part=s.section(",",0,0);
630 num=part.right(part.length() - 3);
634 return false; // in a subtree there is no center
639 lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
642 lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
646 s=s.right(s.length() - part.length() -1 );
653 void LinkableMapObj::setDockPos()
655 cout <<"LMO::setDockPos()\n";
658 QPoint LinkableMapObj::getChildPos()
663 QPoint LinkableMapObj::getParPos()
668 QPoint LinkableMapObj::getRelPos()
671 /* FIXME not needed? relPos was moved in 1.7.10 from
672 floatobj to linkablemapobj. Before we had:
674 if (!parObj) return QPoint (0,0);
676 absPos.x() - parObj->x(),
677 absPos.y() - parObj->y()
683 void LinkableMapObj::setUseOrientation (const bool &b)
685 if (useOrientation!=b)
692 LinkOrient LinkableMapObj::getOrientation()
697 int LinkableMapObj::getDepth()
702 void LinkableMapObj::setMapEditor (MapEditor *me)
707 MapEditor* LinkableMapObj::getMapEditor ()
712 QPoint LinkableMapObj::getRandPos()
714 // Choose a random position with given distance to parent:
715 double a=rand()%360 * 2 * M_PI / 360;
716 return QPoint ( (int)( + 150*cos (a)),
717 (int)( + 150*sin (a)));
720 void LinkableMapObj::alignRelativeTo (QPoint ref)
722 // FIXME testing, seems not to be used right now...
723 cout << "LMO::alignRelTo ref="<<ref<<endl;
726 void LinkableMapObj::reposition()
730 // only calculate the sizes once. If the deepest LMO changes its height,
731 // all upper LMOs have to change, too.
732 calcBBoxSizeWithChilds();
734 alignRelativeTo ( QPoint (absPos.x(),
735 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
738 // This is only important for moving branches:
739 // For editing a branch it isn't called...
740 alignRelativeTo ( QPoint (absPos.x(),
741 absPos.y()-(bboxTotal.height()-bbox.height())/2) );
745 void LinkableMapObj::requestReposition()
747 if (!repositionRequest)
749 // Pass on the request to parental objects, if this hasn't
751 repositionRequest=true;
752 if (parObj) parObj->requestReposition();
756 void LinkableMapObj::forceReposition()
758 // Sometimes a reposition has to be done immediatly: For example
759 // if the note editor flag changes, there is no user event in mapeditor
760 // which could collect requests for a reposition.
761 // Then we have to call forceReposition()
762 // But no rule without exception: While loading a map or undoing it,
763 // we want to block expensive repositioning, but just do it once at
764 // the end, thus check first:
766 if (mapEditor->isRepositionBlocked()) return;
768 // Pass on the request to parental objects, if this hasn't been done yet
771 parObj->forceReposition();
776 bool LinkableMapObj::repositionRequested()
778 return repositionRequest;
782 void LinkableMapObj::setSelBox()
784 selbox->setX (clickBox.x() );
785 selbox->setY (clickBox.y() );
786 selbox->setSize (clickBox.width(), clickBox.height() );
789 void LinkableMapObj::select()
795 setVisibility (visible);
799 void LinkableMapObj::unselect()
803 // Maybe we have to hide the link:
804 setVisibility (visible);
807 void LinkableMapObj::parabel (Q3PointArray &ya, double p1x, double p1y, double p2x, double p2y)
810 double vx=p2x - p1x; // V=P2-P1
813 double dx; // delta x during calculation of parabel
815 double pnx; // next point
819 if (vx > -0.0001 && vx < 0.0001)
825 ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
826 for (i=1;i<=arcsegs;i++)
829 pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
830 ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
836 QString LinkableMapObj::getLinkAttr ()
838 if (hideLinkUnselected)
839 return attribut ("hideLink","true");
841 return attribut ("hideLink","false");