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