linkablemapobj.cpp
author insilmaril
Wed Mar 01 14:39:04 2006 +0000 (2006-03-01)
changeset 224 bbb4eeefcc94
parent 175 728f51b71e71
child 225 d5c70aaca22d
permissions -rw-r--r--
1.7.10 includeImagesHorizontally implemented
     1 #include <math.h>
     2 
     3 #include "linkablemapobj.h"
     4 #include "branchobj.h"
     5 #include "mapeditor.h"
     6 
     7 #include "version.h"
     8 
     9 
    10 /////////////////////////////////////////////////////////////////
    11 // LinkableMapObj
    12 /////////////////////////////////////////////////////////////////
    13 
    14 LinkableMapObj::LinkableMapObj():MapObj()
    15 {
    16   //  cout << "Const LinkableMapObj ()\n";
    17     init ();
    18 }
    19 
    20 LinkableMapObj::LinkableMapObj(QCanvas* c) :MapObj(c)
    21 {
    22 //    cout << "Const LinkableMapObj\n";
    23     init ();
    24 }
    25 
    26 LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas)
    27 {
    28     copy (lmo);
    29 }
    30 
    31 LinkableMapObj::~LinkableMapObj()
    32 {
    33     delete (bottomline);
    34     delete (selbox);
    35 	delete (frame);
    36 	delLink();
    37 }
    38 
    39 void LinkableMapObj::delLink()
    40 {
    41 	switch (style)
    42 	{
    43 		case StyleLine:
    44 			delete (l);
    45 			break;
    46 		case StyleParabel:
    47 			segment.clear();
    48 			break;
    49 		case StylePolyLine:
    50 			delete (p);
    51 			delete (l);
    52 			break;
    53 		case StylePolyParabel:
    54 			delete (p);
    55 			segment.clear();
    56 			break;
    57 		default:
    58 			break;
    59 	}		
    60 }
    61 
    62 void LinkableMapObj::init ()
    63 {
    64     depth=-1;	
    65 	mapEditor=NULL;
    66     childObj=NULL;
    67     parObj=NULL;
    68     parObjTmpBuf=NULL;
    69     parPos=QPoint(0,0);
    70     childPos=QPoint(0,0);
    71 	link2ParPos=false;
    72     l=NULL;
    73     orientation=OrientUndef;
    74     linkwidth=20;		
    75 	thickness_start=8;
    76     style=StyleUndef;
    77 	linkpos=LinkBottom;
    78     segment.setAutoDelete (TRUE);
    79     arcsegs=13;
    80 	QPointArray pa(arcsegs*2+2);
    81     
    82     bottomline=new QCanvasLine(canvas);
    83     bottomline->setPen( QPen(linkcolor, 1) );
    84     bottomline->setZ(Z_LINK);
    85     bottomline->show();
    86 
    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) ));
    92     selbox->hide();
    93     selected=false;
    94 
    95 	hideLinkUnselected=false;
    96 
    97 	topPad=botPad=leftPad=rightPad=0;
    98 
    99 	// initialize frame
   100 	frame = new FrameObj (canvas);
   101 	
   102 	repositionRequest=false;
   103 
   104 	// Rel Positions
   105 	relPos=QPoint(0,0);
   106 	useOrientation=true;
   107 }
   108 
   109 void LinkableMapObj::copy (LinkableMapObj* other)
   110 {
   111     MapObj::copy(other);
   112 	bboxTotal=other->bboxTotal;
   113     setLinkStyle(other->style);
   114     setLinkColor (other->linkcolor);
   115 	relPos=other->relPos;
   116 	useOrientation=other->useOrientation;
   117 
   118 }
   119 
   120 void LinkableMapObj::setChildObj(LinkableMapObj* o)
   121 {
   122     childObj=o;
   123 }
   124 
   125 void LinkableMapObj::setParObj(LinkableMapObj* o)
   126 {
   127     parObj=o;
   128 	mapEditor=parObj->getMapEditor();
   129 }
   130 
   131 void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int)
   132 {
   133 }
   134 
   135 void LinkableMapObj::unsetParObjTmp()
   136 {
   137 }
   138 
   139 bool LinkableMapObj::hasParObjTmp()
   140 {
   141 	if (parObjTmpBuf) return true;
   142 	return false;
   143 }
   144 
   145 void LinkableMapObj::setUseRelPos (const bool &b)
   146 {
   147 	useRelPos=b;
   148 }
   149 
   150 void LinkableMapObj::setRelPos()
   151 {
   152 	if (useOrientation)
   153 	{
   154 		if (parObj->getOrientation()==OrientLeftOfCenter)
   155 			relPos.setX ( parObj->x() +parObj->width() - bbox.width() -absPos.x());
   156 		else	
   157 			relPos.setX (absPos.x() - parObj->x() );
   158 	}
   159 	else
   160 		relPos.setX (absPos.x() - parObj->x() );
   161 	relPos.setY (absPos.y() - parObj->y() );
   162 	if (parObj)
   163 	{	
   164 		parObj->calcBBoxSize();
   165 		parObj->requestReposition();
   166 	}	
   167 }
   168 
   169 void LinkableMapObj::setRelPos(const QPoint &p)
   170 {
   171 	relPos=p;
   172 	if (parObj)
   173 	{	parObj->calcBBoxSize();
   174 		parObj->requestReposition();
   175 	}	
   176 }
   177 
   178 int LinkableMapObj::getTopPad()
   179 {
   180 	return topPad;
   181 }
   182 
   183 int LinkableMapObj::getLeftPad()
   184 {
   185 	return leftPad;
   186 }
   187 
   188 int LinkableMapObj::getRightPad()
   189 {
   190 	return rightPad;
   191 }
   192 
   193 LinkStyle LinkableMapObj::getDefLinkStyle ()
   194 {
   195 	if (!mapEditor) return StyleUndef;
   196 
   197 	LinkStyle ls=mapEditor->getLinkStyle();
   198 	switch (ls)
   199 	{
   200 		case StyleLine: 
   201 			return ls;
   202 			break;
   203 		case StyleParabel:
   204 			return ls;
   205 			break;
   206 		case StylePolyLine:	
   207 			if (depth>1)
   208 				return StyleLine;
   209 			else	
   210 				return ls;
   211 			break;
   212 		case StylePolyParabel:	
   213 			if (depth>1)
   214 				return StyleParabel;
   215 			else	
   216 				return ls;
   217 			break;
   218 		default: 
   219 			break;	
   220 	}	
   221 	return StyleUndef;
   222 }
   223 
   224 void LinkableMapObj::setLinkStyle(LinkStyle newstyle)
   225 {
   226 	//if (newstyle=style) return;
   227 	delLink();
   228 		
   229 	style=newstyle;
   230 
   231     if (childObj!=NULL && parObj != NULL)
   232     {
   233 		int i;
   234 		QCanvasLine* cl;
   235 		switch (style)
   236 		{
   237 			case StyleUndef:
   238 				bottomline->hide();
   239 				break;
   240 			case StyleLine: 
   241 				l = new QCanvasLine(canvas);
   242 				l->setPen( QPen(linkcolor, 1) );
   243 				l->setZ(Z_LINK);
   244 				if (visible)
   245 					l->show();
   246 				else
   247 					l->hide();
   248 				break;
   249 			case StyleParabel:
   250 				for (i=0;i<arcsegs;i++)
   251 				{
   252 					cl = new QCanvasLine(canvas);
   253 					cl->setPen( QPen(linkcolor, 1) );
   254 					cl->setPoints( 0,0,i*10,100);
   255 					cl->setZ(Z_LINK);
   256 					if (visible)
   257 						cl->show();
   258 					else
   259 						cl->hide();
   260 					segment.append(cl);
   261 				}
   262 				pa0.resize (arcsegs+1);
   263 				break;
   264 			case StylePolyLine:	
   265 				p = new QCanvasPolygon(canvas);
   266 				p->setBrush( linkcolor );
   267 				p->setZ(Z_LINK);
   268 				if (visible)
   269 					p->show();
   270 				else
   271 					p->hide();
   272 				pa0.resize (3);
   273 				// TODO a bit awkward: draw the lines additionally to polygon, to avoid
   274 				// missing pixels, when polygon is extremly flat
   275 				l = new QCanvasLine(canvas);
   276 				l->setPen( QPen(linkcolor, 1) );
   277 				l->setZ(Z_LINK);
   278 				if (visible)
   279 					l->show();
   280 				else
   281 					l->hide();
   282 				break;
   283 			case StylePolyParabel:	
   284 				p = new QCanvasPolygon(canvas);
   285 				p->setBrush( linkcolor );
   286 				p->setZ(Z_LINK);
   287 				if (visible)
   288 					p->show();
   289 				else
   290 					p->hide();
   291 				pa0.resize (arcsegs*2+2);
   292 				pa1.resize (arcsegs+1);
   293 				pa2.resize (arcsegs+1);
   294 
   295 				// TODO a bit awkward: draw the lines additionally 
   296 				// to polygon, to avoid missing pixels, 
   297 				// if polygon is extremly flat
   298 				for (i=0;i<arcsegs;i++)
   299 				{
   300 					cl = new QCanvasLine(canvas);
   301 					cl->setPen( QPen(linkcolor, 1) );
   302 					cl->setPoints( 0,0,i*10,100);
   303 					cl->setZ(Z_LINK);
   304 					if (visible)
   305 						cl->show();
   306 					else
   307 						cl->hide();
   308 					segment.append(cl);
   309 				}
   310 				break;
   311 			default: 
   312 				break;	
   313 		}	
   314 	} 
   315 }
   316 
   317 LinkStyle LinkableMapObj::getLinkStyle()
   318 {
   319 	return style;
   320 }
   321 
   322 void LinkableMapObj::setHideLinkUnselected(bool b)
   323 {
   324 	hideLinkUnselected=b;
   325 	setVisibility (visible);
   326 	updateLink();
   327 }
   328 
   329 bool LinkableMapObj::getHideLinkUnselected()
   330 {
   331 	return hideLinkUnselected;
   332 }
   333 
   334 void LinkableMapObj::setLinkPos(LinkPos lp)
   335 {
   336 	linkpos=lp;
   337 }
   338 
   339 LinkPos LinkableMapObj::getLinkPos()
   340 {
   341 	return linkpos;
   342 }
   343 
   344 
   345 void LinkableMapObj::setLinkColor()
   346 {
   347 	// Overloaded in BranchObj and childs
   348 	// here only set default color
   349 	if (mapEditor)
   350 		setLinkColor (mapEditor->getDefLinkColor());
   351 }
   352 
   353 void LinkableMapObj::setLinkColor(QColor col)
   354 {
   355 	linkcolor=col;
   356     bottomline->setPen( QPen(linkcolor, 1) );
   357 	QCanvasLine *cl;
   358 	switch (style)
   359 	{
   360 		case StyleLine:
   361 			l->setPen( QPen(col,1));
   362 			break;	
   363 		case StyleParabel:	
   364 			for (cl=segment.first(); cl; cl=segment.next() )
   365 				cl->setPen( QPen(col,1));
   366 			break;
   367 		case StylePolyLine:
   368 			p->setBrush( QBrush(col));
   369 			l->setPen( QPen(col,1));
   370 			break;
   371 		case StylePolyParabel:	
   372 			p->setBrush( QBrush(col));
   373 			for (cl=segment.first(); cl; cl=segment.next() )
   374 				cl->setPen( QPen(col,1));
   375 			break;
   376 		default:
   377 			break;
   378 	} // switch (style)	
   379 }
   380 
   381 QColor LinkableMapObj::getLinkColor()
   382 {
   383 	return linkcolor;
   384 }
   385 
   386 FrameType LinkableMapObj::getFrameType()
   387 {
   388 	return frame->getFrameType();
   389 }
   390 
   391 void LinkableMapObj::setFrameType(const FrameType &t)
   392 {
   393 	frame->setFrameType(t);
   394 	calcBBoxSize();
   395 	positionBBox();
   396 	requestReposition();
   397 }
   398 
   399 void LinkableMapObj::setFrameType(const QString &t)
   400 {
   401 	frame->setFrameType(t);
   402 	calcBBoxSize();
   403 	positionBBox();
   404 	requestReposition();
   405 }
   406 
   407 void LinkableMapObj::setVisibility (bool v)
   408 {
   409 	QCanvasLine* cl;
   410 	MapObj::setVisibility (v);
   411 	bool visnow=visible;
   412 	if (hideLinkUnselected && !selected)
   413 		visnow=false;
   414 
   415 	if (visnow) 
   416 	{
   417 		bottomline->show();
   418 		switch (style)
   419 		{
   420 			case StyleLine:
   421 				if (l) l->show();
   422 				break;
   423 			case StyleParabel:	
   424 				for (cl=segment.first(); cl; cl=segment.next() )
   425 					cl->show();
   426 				break;	
   427 			case StylePolyLine:
   428 				if (p) p->show();
   429 				if (l) l->show();
   430 				break;
   431 			case StylePolyParabel:	
   432 				for (cl=segment.first(); cl; cl=segment.next() )
   433 					cl->show();
   434 				if (p) p->show();
   435 				break;
   436 			default:
   437 				break;
   438 		}
   439 	} else 
   440 	{
   441 		bottomline->hide();
   442 		switch (style)
   443 		{
   444 			case StyleLine:
   445 				if (l) l->hide();
   446 				break;
   447 			case StyleParabel:	
   448 				for (cl=segment.first(); cl; cl=segment.next() )
   449 					cl->hide();
   450 				break;	
   451 			case StylePolyLine:
   452 				if (p) p->hide();
   453 				if (l) l->hide();
   454 				break;
   455 			case StylePolyParabel:	
   456 				for (cl=segment.first(); cl; cl=segment.next() )
   457 					cl->hide();
   458 				if (p) p->hide();
   459 				break;
   460 			default:
   461 				break;
   462 		}
   463 	}	
   464 }
   465 
   466 void LinkableMapObj::updateLink()
   467 {
   468     // needs:
   469     //	childPos of parent
   470     //	orient   of parent
   471     //	style
   472     // 
   473     // sets:
   474     //	orientation
   475     //	childPos
   476     //	parPos
   477 	//  bottomlineY
   478     //	drawing of the link itself
   479 
   480 
   481 	// updateLink is called from move, but called from constructor we don't
   482 	// have parents yet...
   483 	if (style==StyleUndef) return;	
   484 
   485 	if (frame->getFrameType() == NoFrame)
   486 		linkpos=LinkBottom;
   487 	else	
   488 		linkpos=LinkMiddle;
   489 	switch (linkpos)
   490 	{
   491 		case LinkMiddle:
   492 			bottomlineY=clickBox.top()+clickBox.height() /2;	// draw link to middle (of frame)
   493 			break;
   494 		default :
   495 			bottomlineY=clickBox.bottom()-1;	// draw link to bottom of bbox
   496 			break;
   497 	}
   498 	
   499     double p2x,p2y;								// Set P2 Before setting
   500 	if (!link2ParPos)
   501 	{
   502 		p2x=QPoint( parObj->getChildPos() ).x();	// P1, we have to look at
   503 		p2y=QPoint( parObj->getChildPos() ).y();	// orientation
   504 	} else	
   505 	{
   506 		p2x=QPoint( parObj->getParPos() ).x();	
   507 		p2y=QPoint( parObj->getParPos() ).y();
   508 	} 
   509 
   510 	LinkOrient orientOld=orientation;
   511 
   512     // Set orientation, first look for orientation of parent
   513     if (parObj->getOrientation() != OrientUndef ) 
   514 		// use the orientation of the parent:
   515 		orientation=parObj->getOrientation();
   516     else
   517     {
   518 		// calc orientation depending on position rel to mapCenter
   519 		if (absPos.x() < QPoint(parObj->getChildPos() ).x() )
   520 			orientation=OrientLeftOfCenter; 
   521 		else
   522 			orientation=OrientRightOfCenter;
   523     }
   524 
   525 	if ((orientation!=orientOld) && (orientOld!= OrientUndef))
   526 	{
   527 		// Orientation just changed. Reorient this subbranch, because move is called
   528 		// before updateLink => Position is still the old one, which could lead to 
   529 		// linking of subranch to itself => segfault
   530 		//
   531 		// Also possible: called in BranchObj::init(), then orientOld==OrientUndef,
   532 		// no need to reposition now
   533 		reposition();
   534 	}
   535 	
   536     if (orientation==OrientLeftOfCenter )
   537     {
   538 		childPos=QPoint (absPos.x(),bottomlineY);
   539 		parPos=QPoint (absPos.x()+ bbox.width(),  bottomlineY );
   540     } else
   541     {
   542 		childPos=QPoint (absPos.x()+ bbox.width(), bottomlineY ); 
   543 		parPos=QPoint (absPos.x(),bottomlineY);
   544     }
   545 
   546 	double p1x=parPos.x();	// Link is drawn from P1 to P2
   547 	double p1y=parPos.y();
   548 
   549 	double vx=p2x - p1x;	// V=P2-P1
   550 	double vy=p2y - p1y;
   551 
   552 	// Draw the horizontal line below heading (from ChildPos to ParPos)
   553 	bottomline->setPoints (qRound(childPos.x()),
   554 		qRound(childPos.y()),
   555 		qRound(p1x),
   556 		qRound(p1y) );
   557 
   558 	double a;	// angle
   559 	if (vx > -0.000001 && vx < 0.000001)
   560 		a=M_PI_2;
   561 	else
   562 		a=atan( vy / vx );
   563 	// "turning point" for drawing polygonal links
   564 	QPoint tp (-qRound(sin (a)*thickness_start), qRound(cos (a)*thickness_start));	
   565 	
   566 	QCanvasLine *cl;
   567 
   568 	int i;
   569 
   570     // Draw the link
   571 	switch (style)
   572 	{
   573 		case StyleLine:
   574 			l->setPoints( qRound (parPos.x()),
   575 				qRound(parPos.y()),
   576 				qRound(p2x),
   577 				qRound(p2y) );
   578 			break;	
   579 		case StyleParabel:	
   580 			parabel (pa0, p1x,p1y,p2x,p2y);
   581 			i=0;
   582 			for (cl=segment.first(); cl; cl=segment.next() )
   583 			{	
   584 				cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y());
   585 				i++;
   586 			}
   587 			break;
   588 		case StylePolyLine:
   589 			pa0[0]=QPoint (qRound(p2x+tp.x()), qRound(p2y+tp.y()));
   590 			pa0[1]=QPoint (qRound(p2x-tp.x()), qRound(p2y-tp.y()));
   591 			pa0[2]=QPoint (qRound (parPos.x()), qRound(parPos.y()) );
   592 			p->setPoints (pa0);
   593 			// here too, draw line to avoid missing pixels
   594 			l->setPoints( qRound (parPos.x()),
   595 				qRound(parPos.y()),
   596 				qRound(p2x),
   597 				qRound(p2y) );
   598 			break;
   599 		case StylePolyParabel:	
   600 			parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y());
   601 			parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y());
   602 			for (i=0;i<=arcsegs;i++)
   603 			{
   604 				// Combine the arrays to a single one
   605 				pa0[i]=pa1[i];
   606 				pa0[i+arcsegs+1]=pa2[arcsegs-i];
   607 			}	
   608 			p->setPoints (pa0);
   609 			i=0;
   610 			for (cl=segment.first(); cl; cl=segment.next() )
   611 			{	
   612 				cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y());
   613 				i++;
   614 			}
   615 			break;
   616 		default:
   617 			break;
   618 	} // switch (style)	
   619 }
   620 	
   621 LinkableMapObj* LinkableMapObj::getChildObj()
   622 {
   623     return childObj;
   624 }
   625 
   626 LinkableMapObj* LinkableMapObj::getParObj()
   627 {
   628     return parObj;
   629 }
   630 
   631 LinkableMapObj* LinkableMapObj::findObjBySelect (QString s)
   632 {
   633 	LinkableMapObj *lmo=this;
   634 	QString part;
   635 	QString typ;
   636 	QString num;
   637 	while (!s.isEmpty() )
   638 	{
   639 		part=s.section(",",0,0);
   640 		typ=part.left (3);
   641 		num=part.right(part.length() - 3);
   642 		if (typ=="mc:")
   643 		{
   644 			if (depth>0)
   645 				return false;	// in a subtree there is no center
   646 			else
   647 				break;
   648 		} else
   649 			if (typ=="bo:")
   650 				lmo=((BranchObj*)(lmo))->getBranchNum (num.toUInt());
   651 			else
   652 				if (typ=="fi:")
   653 					lmo=((BranchObj*)(lmo))->getFloatImageNum (num.toUInt());
   654 		if (!lmo) break;
   655 		
   656 		if (s.contains(","))
   657 			s=s.right(s.length() - part.length() -1 );
   658 		else	
   659 			break;
   660 	}
   661 	return lmo;
   662 }
   663 
   664 QPoint LinkableMapObj::getChildPos()
   665 {
   666     return childPos;
   667 }
   668 
   669 QPoint LinkableMapObj::getParPos()
   670 {
   671     return parPos;
   672 }
   673 
   674 QPoint LinkableMapObj::getRelPos()
   675 {
   676 	if (!parObj) return QPoint (0,0);
   677     return QPoint(
   678 		absPos.x() - parObj->x(),
   679 		absPos.y() - parObj->y()
   680 	);
   681 }
   682 
   683 
   684 void LinkableMapObj::setUseOrientation (const bool &b)
   685 {	
   686 	if (useOrientation!=b)
   687 	{
   688 		useOrientation=b;
   689 		requestReposition();
   690 	}	
   691 }
   692 
   693 LinkOrient LinkableMapObj::getOrientation()
   694 {
   695     return orientation;
   696 }
   697 
   698 int LinkableMapObj::getDepth()
   699 {
   700     return depth;
   701 }
   702 
   703 void LinkableMapObj::setMapEditor (MapEditor *me)
   704 {
   705 	mapEditor=me;
   706 }
   707 
   708 MapEditor* LinkableMapObj::getMapEditor ()
   709 {
   710 	return mapEditor;
   711 }
   712 
   713 QPoint LinkableMapObj::getRandPos()
   714 {
   715 	// Choose a random position with given distance to parent:
   716 	double a=rand()%360 * 2 * M_PI / 360;
   717     return QPoint ( (int)( + 150*cos (a)),
   718                     (int)( + 150*sin (a)));
   719 }
   720 
   721 void LinkableMapObj::alignRelativeTo (QPoint ref)
   722 {
   723 	// FIXME testing, seems not to be used right now...
   724 	cout << "LMO::alignRelTo   ref="<<ref<<endl;
   725 }
   726 
   727 void LinkableMapObj::reposition()
   728 {
   729 	if (depth==0)
   730 	{
   731 		// only calculate the sizes once. If the deepest LMO changes its height,
   732 		// all upper LMOs have to change, too.
   733 		calcBBoxSizeWithChilds();
   734 
   735 	    alignRelativeTo ( QPoint (absPos.x(),
   736 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   737 	} else
   738 	{
   739 		// This is only important for moving branches:
   740 		// For editing a branch it isn't called...
   741 	    alignRelativeTo ( QPoint (absPos.x(),
   742 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   743 	}
   744 }
   745 
   746 void LinkableMapObj::requestReposition()
   747 {
   748 	if (!repositionRequest)
   749 	{
   750 		// Pass on the request to parental objects, if this hasn't
   751 		// been done yet
   752 		repositionRequest=true;
   753 		if (parObj) parObj->requestReposition();
   754 	}
   755 }
   756 
   757 void LinkableMapObj::forceReposition()
   758 {
   759 	// Sometimes a reposition has to be done immediatly: For example
   760 	// if the note editor flag changes, there is no user event in mapeditor
   761 	// which could collect requests for a reposition.
   762 	// Then we have to call forceReposition()
   763 	// But no rule without exception: While loading a map or undoing it,
   764 	// we want to block expensive repositioning, but just do it once at
   765 	// the end, thus check first:
   766 
   767 	if (mapEditor->isRepositionBlocked()) return;
   768 	
   769 	// Pass on the request to parental objects, if this hasn't been done yet
   770 	
   771 	if (parObj) 
   772 		parObj->forceReposition(); 
   773 	else 
   774 		reposition(); 
   775 }
   776 
   777 bool LinkableMapObj::repositionRequested()
   778 {
   779 	return repositionRequest;
   780 }
   781 
   782 
   783 void LinkableMapObj::setSelBox()
   784 {
   785     selbox->setX (clickBox.x() );
   786     selbox->setY (clickBox.y() );
   787     selbox->setSize (clickBox.width(), clickBox.height() );
   788 }
   789 
   790 void LinkableMapObj::select()
   791 {
   792 	setSelBox();
   793     selected=true;
   794     selbox->show();
   795 	setVisibility (visible);
   796 }
   797 
   798 
   799 void LinkableMapObj::unselect()
   800 {
   801     selected=false;
   802     selbox->hide();
   803 	setVisibility (visible);
   804 }
   805 
   806 void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y)
   807 
   808 {
   809 	double vx=p2x - p1x;	// V=P2-P1
   810 	double vy=p2y - p1y;
   811 
   812 	double dx;				// delta x during calculation of parabel
   813 	
   814 	double pnx;				// next point
   815 	double pny;
   816 	double m;
   817 
   818 	if (vx > -0.0001 && vx < 0.0001)
   819 		m=0;
   820 	else	
   821 		m=(vy / (vx*vx));
   822 	dx=vx/(arcsegs);
   823 	int i;
   824 	ya.setPoint (0,QPoint (qRound(p1x),qRound(p1y)));
   825 	for (i=1;i<=arcsegs;i++)
   826 	{	
   827 		pnx=p1x+dx;
   828 		pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y();
   829 		ya.setPoint (i,QPoint (qRound(pnx),qRound(pny)));
   830 		p1x=pnx;
   831 		p1y=pny;
   832 	}	
   833 }
   834 
   835 QString LinkableMapObj::getLinkAttr ()
   836 {
   837 	if (hideLinkUnselected)
   838 		return attribut ("hideLink","true");
   839 	else
   840 		return attribut ("hideLink","false");
   841 	
   842 }