branchobj.cpp
author insilmaril
Wed, 09 Sep 2009 12:57:06 +0000
changeset 793 cac93797c580
parent 792 7d67be709091
child 794 d922fb6ea482
permissions -rw-r--r--
more fixes for collision detection
     1 #include "branchobj.h"
     2 
     3 #include "branchitem.h"
     4 #include "geometry.h"
     5 #include "mapeditor.h"
     6 #include "mainwindow.h"
     7 #include "misc.h"
     8 
     9 extern FlagRow *standardFlagsMaster;
    10 extern FlagRow *systemFlagsMaster;
    11 
    12 /////////////////////////////////////////////////////////////////
    13 // BranchObj
    14 /////////////////////////////////////////////////////////////////
    15 
    16 BranchObj::BranchObj (QGraphicsScene* s,TreeItem *ti):OrnamentedObj (s)
    17 {
    18 //    cout << "Const BranchObj (s)  \n";
    19 	parObj=NULL;
    20     scene=s;
    21 	treeItem=ti;
    22 	init();
    23 }
    24 
    25 /*
    26 BranchObj::BranchObj (QGraphicsScene* s, LinkableMapObj* p):OrnamentedObj (s)// FIXME-3 needed at all?
    27 {
    28 //    cout << "Const BranchObj (s,p)\n";
    29     scene=s;
    30     setParObj (p);	
    31 	if (treeItem->depth()==1)	// FIXME-3 needed to recursively calc depth?
    32 		// Calc angle to mapCenter if I am a mainbranch
    33 		// needed for reordering the mainbranches clockwise 
    34 		// around mapcenter 
    35 		angle=getAngle (QPointF (x() - parObj->getChildPos().x() , 
    36 								(y() - parObj->getChildPos().y() ) ) );
    37     init();
    38 }
    39 */
    40 
    41 BranchObj::~BranchObj ()
    42 {
    43 //	cout << "Destr BranchObj of "<<this<<" ("<<treeItem->getHeading().toStdString()<<")"<<endl;
    44 
    45 	// If I'm animated, I need to un-animate myself first
    46 	if (anim.isAnimated() )
    47 	{
    48 		anim.setAnimated (false);
    49 		VymModel *model=treeItem->getModel();
    50 		model->stopAnimation (this);
    51 	}
    52 
    53 	// Check, if this branch was the last child to be deleted
    54 	// If so, unset the scrolled flags in parent // FIXME-2 better do this in model?
    55 
    56 	/*
    57 	BranchObj *po=(BranchObj*)parObj;
    58 	BranchObj *bo;
    59 	if (po)
    60 	{
    61 		bo=((BranchObj*)parObj)->getLastBranch();
    62 		if (bo) po->unScroll();
    63 	}
    64 	*/
    65 	clear();
    66 }
    67 
    68 bool BranchObj::operator< ( const BranchObj & other )
    69 {
    70     return  angle < other.angle;
    71 }
    72 
    73 bool BranchObj::operator== ( const BranchObj & other )
    74 {
    75     return angle == other.angle;
    76 }
    77 
    78 void BranchObj::init () 
    79 {
    80 	if (parObj)
    81 	{
    82 		absPos=getRandPos();
    83 		absPos+=parObj->getChildPos();
    84 	}
    85 }
    86 
    87 void BranchObj::copy (BranchObj* other)
    88 {
    89     OrnamentedObj::copy(other);
    90 
    91 	setVisibility (other->visible);
    92 
    93 	angle=other->angle;
    94 
    95     positionBBox();
    96 }
    97 
    98 void BranchObj::clear() 
    99 {
   100 	//setVisibility (true); //FIXME-4 needed?
   101 
   102 	while (!xlink.isEmpty())
   103 		delete xlink.takeFirst();
   104 }
   105 
   106 bool isAbove (BranchObj* a, BranchObj *b)
   107 {
   108 	if (a->angle < b->angle)
   109 		return true;
   110 	else	
   111 		return false;
   112 }
   113 
   114 void BranchObj::setParObjTmp(LinkableMapObj* lmo, QPointF m, int off)
   115 {
   116 	// Temporary link to lmo
   117 	// m is position of mouse pointer 
   118 	// offset 0: default 1: below lmo   -1 above lmo  (if possible)
   119 
   120 	BranchItem *pi=(BranchItem*)(lmo->getTreeItem()->parent());
   121 	int pi_depth=pi->depth();
   122 	BranchObj* o=(BranchObj*)(lmo);
   123 	if (!parObjTmpBuf) 
   124 		parObjTmpBuf=parObj;
   125 
   126 	// ignore mapcenter and mainbranch	//FIXME-3 MCO meanwhile also could be relinked
   127 	if (pi_depth<2) off=0;
   128 	if (off==0)
   129 		link2ParPos=false;
   130 	else
   131 		link2ParPos=true;
   132 	parObj=o;
   133 
   134 	// setLinkStyle calls updateLinkGeometry, only set it once
   135 	//LinkableMapObj::Style ls=getDefLinkStyle (lmo->getTreeItem() );
   136 	//if (style!=ls ) setLinkStyle (ls);
   137 	setLinkStyle (lmo->getDefLinkStyle (lmo->getTreeItem()));
   138 
   139 	// Move temporary to new position at destination
   140 	// Usually the positioning would be done by reposition(),
   141 	// but then also the destination branch would "Jump" around...
   142 	// Better just do it approximately
   143 	if (parObj->getTreeItem()->depth()==0)	
   144 	{	// new parent is a mapcenter
   145 
   146 		//FIXME-2 rewrite to us new normalize QPointF p= normalize ( QPointF (m.x() - o->getChildPos().x(),
   147 		//								  m.y() - o->getChildPos().y() ));
   148 		QPointF p= ( QPointF (m.x() - o->getChildPos().x(),
   149 									  m.y() - o->getChildPos().y() ));
   150 		if (p.x()<0) p.setX( p.x()-bbox.width() );
   151 		move2RelPos (p);
   152 	} else
   153 	{	
   154 		qreal y;
   155 		if (off==0)
   156 		{
   157 			// new parent is just a branch, link to it
   158 			QRectF t=o->getBBoxSizeWithChildren();
   159 			if (o->getTreeItem()->getLastBranch())
   160 				y=t.y() + t.height() ;
   161 			else
   162 				y=t.y();
   163 
   164 		} else
   165 		{
   166 			if (off<0)
   167 				// we want to link above lmo
   168 				y=o->y() - height() + 5;
   169 			else	
   170 				// we want to link below lmo
   171 				// Bottom of sel should be 5 pixels above
   172 				// the bottom of the branch _below_ the target:
   173 				// Don't try to find that branch, guess 12 pixels
   174 				y=o->getChildPos().y()  -height() + 12; 
   175 		}	
   176 		if (o->getOrientation()==LinkableMapObj::LeftOfCenter)
   177 			move ( o->getChildPos().x() - linkwidth, y );
   178 		else	
   179 			move (o->getChildPos().x() + linkwidth, y );
   180 	}	
   181 
   182 	// updateLinkGeometry is called implicitly in move
   183 	requestReposition();	
   184 }
   185 
   186 void BranchObj::unsetParObjTmp()
   187 {
   188 	if (parObjTmpBuf) 
   189 	{
   190 		link2ParPos=false;
   191 		parObj=parObjTmpBuf;
   192 		parObjTmpBuf=NULL;
   193 		setLinkStyle (getDefLinkStyle(treeItem->parent() ) );
   194 		updateLinkGeometry();
   195 	}		
   196 }
   197 
   198 void BranchObj::setVisibility(bool v, int toDepth)
   199 {
   200 	BranchItem *bi=(BranchItem*)treeItem;
   201     if (bi->depth() <= toDepth)
   202     {
   203 		frame->setVisibility(v);
   204 		heading->setVisibility(v);
   205 		systemFlags->setVisibility(v);
   206 		standardFlags->setVisibility(v);
   207 		LinkableMapObj::setVisibility (v);
   208 		int i;
   209 		for (i=0; i<treeItem->imageCount(); ++i)
   210 			treeItem->getImageObjNum(i)->setVisibility (v);
   211 		for (i=0; i<treeItem->xlinkCount(); ++i)	
   212 			treeItem->getXLinkObjNum(i)->setVisibility ();	
   213 
   214 		// Only change children, if I am not scrolled
   215 		if (! bi->isScrolled() && (bi->depth() < toDepth))
   216 		{
   217 			// Now go recursivly through all children //FIXME-3 are there multiple calls for lower level items???
   218 			for (i=0; i<treeItem->branchCount(); ++i)
   219 				treeItem->getBranchObjNum(i)->setVisibility (v,toDepth);	
   220 		}
   221     } // depth <= toDepth	
   222 	requestReposition();
   223 }	
   224 
   225 void BranchObj::setVisibility(bool v)
   226 {
   227     setVisibility (v,MAX_DEPTH);
   228 }
   229 
   230 
   231 void BranchObj::setLinkColor ()
   232 {
   233 	// Overloaded from LinkableMapObj
   234 	// BranchObj can use color of heading
   235 
   236 	VymModel *model=treeItem->getModel();
   237 	if (model)
   238 	{
   239 		if (model->getMapLinkColorHint()==HeadingColor)
   240 			LinkableMapObj::setLinkColor (heading->getColor() );
   241 		else	
   242 			LinkableMapObj::setLinkColor ();
   243 	}		
   244 }
   245 
   246 void BranchObj::updateContentSize()
   247 {
   248 	calcBBoxSize();
   249 	positionBBox();
   250 	requestReposition();
   251 }
   252 
   253 void BranchObj::positionContents()
   254 {
   255 	for (int i=0; i<treeItem->imageCount(); ++i)
   256 		treeItem->getImageObjNum(i)->reposition();
   257 	OrnamentedObj::positionContents();
   258 }
   259 
   260 void BranchObj::move (double x, double y)
   261 {
   262 	OrnamentedObj::move (x,y);
   263 	FloatImageObj *fio;
   264     for (int i=0; i<treeItem->imageCount(); ++i )
   265 	{
   266 		fio=treeItem->getImageObjNum(i);
   267 		if (fio) fio->reposition();
   268 	}
   269     positionBBox();
   270 }
   271 
   272 void BranchObj::move (QPointF p)
   273 {
   274 	move (p.x(), p.y());
   275 }
   276 
   277 void BranchObj::moveBy (double x, double y)
   278 {
   279 	OrnamentedObj::moveBy (x,y);
   280 	for (int i=0; i<treeItem->branchCount(); ++i)
   281 		treeItem->getBranchObjNum(i)->moveBy (x,y);
   282     positionBBox();
   283 }
   284 	
   285 void BranchObj::moveBy (QPointF p)
   286 {
   287 	moveBy (p.x(), p.y());
   288 }
   289 
   290 
   291 void BranchObj::positionBBox()
   292 {
   293 	QPointF ap=getAbsPos();
   294 	bbox.moveTopLeft (ap);
   295 	positionContents();
   296 
   297 	// set the frame
   298 	frame->setRect(QRectF(bbox.x(),bbox.y(),bbox.width(),bbox.height() ) );
   299 
   300 	//Update links to other branches
   301 	XLinkObj *xlo;
   302 	for (int i=0; i<treeItem->xlinkCount(); ++i)	
   303 	{
   304 		xlo=treeItem->getXLinkObjNum(i);
   305 		if (xlo) xlo->updateXLink();
   306 	}	
   307 }
   308 
   309 void BranchObj::calcBBoxSize()
   310 {
   311     QSizeF heading_r=heading->getSize();
   312     qreal heading_w=(qreal) heading_r.width() ;
   313     qreal heading_h=(qreal) heading_r.height() ;
   314     QSizeF sysflags_r=systemFlags->getSize();
   315 	qreal sysflags_h=sysflags_r.height();
   316 	qreal sysflags_w=sysflags_r.width();
   317     QSizeF stanflags_r=standardFlags->getSize();
   318 	qreal stanflags_h=stanflags_r.height();
   319 	qreal stanflags_w=stanflags_r.width();
   320     qreal w;
   321     qreal h;
   322 
   323 	// set width to sum of all widths
   324 	w=heading_w + sysflags_w + stanflags_w;
   325 	// set height to maximum needed height
   326 	h=max (sysflags_h,stanflags_h);
   327 	h=max (h,heading_h);
   328 
   329 	// Save the dimension of flags and heading
   330 	ornamentsBBox.setSize ( QSizeF(w,h));
   331 
   332 	// clickBox includes Flags and Heading
   333     clickBox.setSize (ornamentsBBox.size() );
   334 
   335 	// Floatimages 
   336 	QPointF rp;
   337 
   338 	topPad=botPad=leftPad=rightPad=0;
   339 	bool incV=((BranchItem*)treeItem)->getIncludeImagesVer();
   340 	bool incH=((BranchItem*)treeItem)->getIncludeImagesHor();
   341 	if (incH || incV)
   342 	{
   343 		FloatImageObj *fio;
   344 		for (int i=0; i<treeItem->imageCount(); ++i )	
   345 		{
   346 			fio=treeItem->getImageObjNum(i);
   347 			rp=fio->getRelPos();
   348 			if (incV)
   349 			{
   350 				if (rp.y() < 0) 
   351 					topPad=max (topPad,-rp.y()-h);
   352 				if (rp.y()+fio->height() > 0)
   353 					botPad=max (botPad,rp.y()+fio->height());
   354 			}		
   355 			if (incH)
   356 			{
   357 				if (orientation==LinkableMapObj::RightOfCenter)
   358 				{
   359 					if (-rp.x()-w > 0) 
   360 						leftPad=max (leftPad,-rp.x()-w);
   361 					if (rp.x()+fio->width() > 0)
   362 						rightPad=max (rightPad,rp.x()+fio->width());
   363 				} else
   364 				{
   365 					if (rp.x()< 0) 
   366 						leftPad=max (leftPad,-rp.x());
   367 					if (rp.x()+fio->width() > w)
   368 						rightPad=max (rightPad,rp.x()+fio->width()-w);
   369 				}
   370 			}		
   371 		}	
   372 		h+=topPad+botPad;
   373 		w+=leftPad+rightPad;
   374 	}
   375 
   376 	// Frame thickness
   377     w+=frame->getPadding();
   378     h+=frame->getPadding();
   379 	
   380 	// Finally set size
   381     bbox.setSize (QSizeF (w,h));
   382 }
   383 
   384 void BranchObj::setDockPos()
   385 {
   386 	if (treeItem->getType()==TreeItem::MapCenter)
   387 	{
   388 		// set childPos to middle of MapCenterObj
   389 		childPos.setX( clickBox.topLeft().x() + clickBox.width()/2 );
   390 		childPos.setY( clickBox.topLeft().y() + clickBox.height()/2 );
   391 		parPos=childPos;		
   392 		for (int i=0; i<treeItem->branchCount(); ++i)
   393 			treeItem->getBranchObjNum(i)->updateLinkGeometry();
   394 
   395 	} else
   396 	{
   397 		// Sets childpos and parpos depending on orientation
   398 		if (getOrientation()==LinkableMapObj::LeftOfCenter )
   399 		{
   400 			childPos=QPointF (
   401 				ornamentsBBox.bottomLeft().x(), 
   402 				bottomlineY);
   403 			parPos=QPointF (
   404 				ornamentsBBox.bottomRight().x(),
   405 				bottomlineY);
   406 		} else
   407 		{
   408 			childPos=QPointF (
   409 				ornamentsBBox.bottomRight().x(), 
   410 				bottomlineY);
   411 			parPos=QPointF (
   412 				ornamentsBBox.bottomLeft().x(),
   413 				bottomlineY);
   414 		}
   415 	}
   416 }
   417 
   418 void BranchObj::updateData()
   419 {
   420 	bool changed=false;
   421 	if (!treeItem)
   422 	{
   423 		qWarning ("BranchObj::udpateHeading treeItem==NULL");
   424 		return;
   425 	}
   426 	QString s=treeItem->getHeading();
   427 	if (s!=heading->text())
   428 	{
   429 		heading->setText (s);
   430 		changed=true;
   431 	}
   432 	QStringList TIactiveFlags=treeItem->activeStandardFlagNames();
   433 
   434 	// Add missing standard flags active in TreeItem
   435 	for (int i=0;i<=TIactiveFlags.size()-1;i++)
   436 	{	
   437 		if (!standardFlags->isActive (TIactiveFlags.at(i) ))
   438 		{
   439 			Flag *f=standardFlagsMaster->getFlag(TIactiveFlags.at(i));
   440 			if (f) standardFlags->activate (f);
   441 			changed=true;
   442 		}
   443 	}
   444 	// Remove standard flags no longer active in TreeItem
   445 	QStringList BOactiveFlags=standardFlags->activeFlagNames();
   446 	for (int i=0;i<BOactiveFlags.size();++i)
   447 		if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
   448 		{
   449 			standardFlags->deactivate (BOactiveFlags.at(i));
   450 			changed=true;
   451 		}	
   452 
   453 	// Add missing system flags active in TreeItem
   454 	TIactiveFlags=treeItem->activeSystemFlagNames();
   455 	for (int i=0;i<TIactiveFlags.size();++i)
   456 	{	
   457 		if (!systemFlags->isActive (TIactiveFlags.at(i) ))
   458 		{
   459 			Flag *f=systemFlagsMaster->getFlag(TIactiveFlags.at(i));
   460 			if (f) systemFlags->activate (f);
   461 			changed=true;
   462 		}
   463 	}
   464 	// Remove system flags no longer active in TreeItem
   465 	BOactiveFlags=systemFlags->activeFlagNames();
   466 	for (int i=0;i<BOactiveFlags.size();++i)
   467 	{
   468 		if (!TIactiveFlags.contains (BOactiveFlags.at(i)))
   469 		{
   470 			systemFlags->deactivate (BOactiveFlags.at(i));
   471 			changed=true;
   472 		}	
   473 	}
   474 	updateContentSize();
   475 }
   476 
   477 void BranchObj::savePosInAngle ()
   478 {
   479 	// Save position in angle
   480 	for (int i=0; i<treeItem->branchCount(); ++i)
   481 		treeItem->getBranchObjNum(i)->angle=i;
   482 }
   483 
   484 void BranchObj::setDefAttr (BranchModification mod)
   485 {
   486 	int fontsize;
   487 	switch (treeItem->depth())
   488 	{
   489 		case 0: fontsize=16; break;
   490 		case 1: fontsize=12; break;
   491 		default: fontsize=10; break;
   492 	}	
   493 	setLinkStyle(getDefLinkStyle(treeItem->parent() ));
   494 	setLinkColor ();
   495 	QFont font("Sans Serif,8,-1,5,50,0,0,0,0,0");
   496 	font.setPointSize(fontsize);
   497 	heading->setFont(font );
   498 
   499 	if (mod==NewBranch)
   500 		setColor (treeItem->getHeadingColor() );
   501 	calcBBoxSize();
   502 }
   503 
   504 void BranchObj::sortChildren() //FIXME-3 not moved to model yet 
   505 {
   506 /*
   507 	int childCount=branch.count(); 
   508 	int curChildIndex;
   509 	bool madeChanges=false;
   510 	do
   511 	{
   512 		madeChanges=false;
   513 		for(curChildIndex=1;curChildIndex<childCount;curChildIndex++){
   514 			BranchObj* curChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex);
   515 			BranchObj* prevChild=(BranchObj*)treeItem->getBranchObjNum(curChildIndex-1);
   516 			if(prevChild->heading->text().compare(curChild->heading->text())>0)
   517 			{
   518 				this->moveBranchUp(curChild);
   519 				madeChanges=true;
   520 			}
   521 		}
   522 	}while(madeChanges);
   523 */
   524 }
   525 
   526 void BranchObj::alignRelativeTo (QPointF ref,bool alignSelf)
   527 {
   528 	qreal th = bboxTotal.height();	
   529 	int depth=treeItem->depth();	// FIXME-3 needed to recursively calc depth?
   530 // TODO testing
   531 /*
   532 
   533 	QString h=QString (depth,' ');
   534 	h+=treeItem->getHeading();
   535 	h+=QString (15,' ');
   536 	h.truncate (15);
   537 	QPointF pp; if (parObj) pp=parObj->getChildPos();
   538 	cout << "BO::alignRelTo ";
   539 	cout<<h.toStdString();
   540 	cout << "    d="<<depth<<
   541 //cout<<  "  ref="<<ref<<
   542       	"  bbox.tL="<<bboxTotal.topLeft()<<
   543 		"  absPos="<<absPos<<
   544 //		"  relPos="<<relPos<<
   545 //		"  parPos="<<pp<<
   546 		"  w="<<bbox.width()<<
   547 		"  h="<<bbox.height()<<
   548 //		"  orient="<<orientation<<
   549 //		"  alignSelf="<<alignSelf<<
   550 //		"  scrolled="<<((BranchItem*)treeItem)->isScrolled()<<
   551 //		"  pad="<<topPad<<","<<botPad<<","<<leftPad<<","<<rightPad<<
   552 //		"  hidden="<<hidden<<
   553 		"  th="<<th<<
   554 		endl;
   555 */
   556 
   557 	setOrientation();
   558 	//updateLinkGeometry();
   559 
   560 	if (depth==1 && parObj)
   561 	{
   562 		// Position relatively, if needed
   563 		//if (useRelPos) move2RelPos (relPos.x(), relPos.y());
   564 
   565 		// Calc angle to mapCenter if I am a mainbranch
   566 		// needed for reordering the mainbranches clockwise 
   567 		// around mapcenter 
   568 		angle=getAngle (QPointF ((int)(x() - parObj->getChildPos().x() ), 
   569 								(int)(y() - parObj->getChildPos().y() ) ) );
   570 	}							
   571 	if (depth>1)
   572     {
   573 		// Align myself depending on orientation and parent, but
   574 		// only if I am not a mainbranch or mapcenter itself
   575 
   576 		if (anim.isAnimated())
   577 		{
   578 			move2RelPos(anim);
   579 		} else
   580 		{
   581 			LinkableMapObj::Orientation o;
   582 			o=parObj->getOrientation();
   583 			if (alignSelf)
   584 				switch (orientation) 
   585 				{
   586 					case LinkableMapObj::LeftOfCenter:
   587 						move (ref.x() - bbox.width(), ref.y() + (th-bbox.height())/2 );
   588 						//move (ref.x() , ref.y() + (th-bbox.height())/2 );
   589 					break;
   590 					case LinkableMapObj::RightOfCenter:	
   591 						move (ref.x() , ref.y() + (th-bbox.height())/2  );
   592 					break;
   593 					default:
   594 						qWarning ("LMO::alignRelativeTo: oops, no orientation given...");
   595 					break;
   596 			}
   597 		}
   598     }		
   599 
   600 	if ( ((BranchItem*)treeItem)->isScrolled() ) return;
   601 
   602     // Set reference point for alignment of children
   603     QPointF ref2;
   604     if (orientation==LinkableMapObj::LeftOfCenter)
   605 		ref2.setX(bbox.topLeft().x() - linkwidth);
   606     else	
   607 		ref2.setX(bbox.topRight().x() + linkwidth);
   608 
   609 	if (depth==1)
   610 		ref2.setY(absPos.y()-(bboxTotal.height()-bbox.height())/2);
   611 	else	
   612 		ref2.setY(ref.y() );	
   613 
   614     // Align the children depending on reference point 
   615 	for (int i=0; i<treeItem->branchCount(); ++i)
   616     {	
   617 		if (!treeItem->getBranchNum(i)->isHidden())
   618 		{
   619 			treeItem->getBranchObjNum(i)->alignRelativeTo (ref2,true);
   620 
   621 			// append next branch below current one
   622 			ref2.setY(ref2.y() + treeItem->getBranchObjNum(i)->getBBoxSizeWithChildren().height() );
   623 		}
   624     }
   625 }
   626 
   627 
   628 void BranchObj::reposition()
   629 {	
   630 /* TODO testing only
   631 	if (!treeItem->getHeading().isEmpty())
   632 		cout << "BO::reposition  "<<qPrintable(treeItem->getHeading())<<endl;
   633 	else	
   634 		cout << "BO::reposition  ???"<<endl;
   635 //	cout << "  orient="<<orientation<<endl;
   636 */		
   637 
   638 	if (treeItem->depth()==0)
   639 	{
   640 		// only calculate the sizes once. If the deepest LMO 
   641 		// changes its height,
   642 		// all upper LMOs have to change, too.
   643 		calcBBoxSizeWithChildren();
   644 		updateLinkGeometry();	// This update is needed if the scene is resized 
   645 						// due to excessive moving of a FIO
   646 
   647 	    alignRelativeTo ( QPointF (absPos.x(),
   648 			absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   649 		//FIXME-2 qSort (branch.begin(),branch.end(), isAbove);
   650 		positionBBox();	// Reposition bbox and contents
   651 	} else
   652 	{
   653 		// This is only important for moving branches:
   654 		// For editing a branch it isn't called...
   655 	    alignRelativeTo ( QPointF (absPos.x(),
   656 							absPos.y()-(bboxTotal.height()-bbox.height())/2) );
   657 	}
   658 }
   659 
   660 void BranchObj::unsetAllRepositionRequests()
   661 {
   662 	repositionRequest=false;
   663 	for (int i=0; i<treeItem->branchCount(); ++i)
   664 		treeItem->getBranchObjNum(i)->unsetAllRepositionRequests();
   665 }
   666 
   667 
   668 QPolygonF BranchObj::shape()
   669 {
   670 	QPolygonF p;
   671 
   672 	QRectF r=getTotalBBox();
   673 	if (orientation==LinkableMapObj::LeftOfCenter)
   674 		p   <<r.bottomLeft()
   675 			<<r.topLeft()
   676 			<<QPointF (bbox.topLeft().x(), r.topLeft().y() )
   677 			<<bbox.topRight()
   678 			<<bbox.bottomRight()
   679 			<<QPointF (bbox.bottomLeft().x(), r.bottomLeft().y() ) ;
   680 	else		
   681 		p   <<r.bottomRight()
   682 			<<r.topRight()
   683 			<<QPointF (bbox.topRight().x(), r.topRight().y() )
   684 			<<bbox.topLeft()
   685 			<<bbox.bottomLeft()
   686 			<<QPointF (bbox.bottomRight().x(), r.bottomRight().y() ) ;
   687 	return p;
   688 }
   689 
   690 QRectF BranchObj::getTotalBBox()
   691 {
   692 	QRectF r=bbox;
   693 
   694 	if ( ((BranchItem*)treeItem)->isScrolled() ) return r;
   695 
   696 	for (int i=0; i<treeItem->branchCount(); ++i)
   697 		if (!treeItem->getBranchNum(i)->isHidden())
   698 			r=addBBox(treeItem->getBranchObjNum(i)->getTotalBBox(),r);
   699 
   700 /* FIXME-3 lots of occurences of treeItem->getBranchObjNum(i) in branchobj.cpp
   701             better check if they are not NULL and maybe simplify...
   702 			(have been NULL at least in calcBBoxSizeWithChilds...)
   703 */			
   704 
   705 	for (int i=0; i<treeItem->imageCount(); ++i)
   706 		if (!treeItem->isHidden())
   707 			r=addBBox(treeItem->getImageObjNum(i)->getTotalBBox(),r);
   708 	return r;
   709 }
   710 
   711 QRectF BranchObj::getBBoxSizeWithChildren()
   712 {
   713 	return bboxTotal;
   714 }
   715 
   716 ConvexPolygon BranchObj::getBoundingPolygon()
   717 {
   718 	if (treeItem->branchCount()==0)
   719 		return MapObj::getBoundingPolygon();
   720 
   721 	QPolygonF p;
   722 	p<<bboxTotal.topLeft();
   723 	p<<bboxTotal.topRight();
   724 	p<<bboxTotal.bottomRight();
   725 	p<<bboxTotal.bottomLeft();
   726 	return p;
   727 }
   728 
   729 void BranchObj::calcBBoxSizeWithChildren()
   730 {	
   731 	// This is initially called only from reposition and
   732 	// and only for mapcenter. So it won't be
   733 	// called more than once for a single user 
   734 	// action
   735 	
   736 
   737 	// Calculate size of LMO including all children (to align them later)
   738 	bboxTotal.setX(bbox.x() );
   739 	bboxTotal.setY(bbox.y() );
   740 
   741 	// if branch is scrolled, ignore children, but still consider floatimages
   742 	BranchItem *bi=(BranchItem*)treeItem;
   743 	if ( bi->isScrolled() ) 
   744 	{
   745 		bboxTotal.setWidth (bbox.width());
   746 		bboxTotal.setHeight(bbox.height());
   747 		return;
   748 	}
   749 	
   750 	if (bi->isHidden())
   751 	{
   752 		bboxTotal.setWidth (0);
   753 		bboxTotal.setHeight(0);
   754 		if (parObj)
   755 		{
   756 			bboxTotal.setX (parObj->x());
   757 			bboxTotal.setY (parObj->y());
   758 		} else
   759 		{
   760 			bboxTotal.setX (bbox.x());
   761 			bboxTotal.setY (bbox.y());
   762 		}
   763 		return;
   764 	}
   765 	
   766 	QRectF r(0,0,0,0);
   767 	QRectF br;
   768 	// Now calculate recursivly
   769 	// sum of heights 
   770 	// maximum of widths 
   771 	// minimum of y
   772 	for (int i=0; i<treeItem->branchCount(); i++)
   773 	{
   774 		if (!bi->getBranchNum(i)->isHidden())
   775 		{
   776 			bi->getBranchObjNum(i)->calcBBoxSizeWithChildren();
   777 			br=bi->getBranchObjNum(i)->getBBoxSizeWithChildren();
   778 			r.setWidth( max (br.width(), r.width() ));
   779 			r.setHeight(br.height() + r.height() );
   780 			if (br.y()<bboxTotal.y()) bboxTotal.setY(br.y());
   781 		}
   782 	}
   783 	// Add myself and also
   784 	// add width of link to sum if necessary
   785 	if (bi->branchCount()<1)
   786 		bboxTotal.setWidth (bbox.width() + r.width() );
   787 	else	
   788 		bboxTotal.setWidth (bbox.width() + r.width() + linkwidth);
   789 	
   790 	bboxTotal.setHeight(max (r.height(),  bbox.height()));
   791 }
   792 
   793 QString BranchObj::getSelectString()
   794 {
   795 	VymModel *model=treeItem->getModel();
   796 	if (model)
   797 		return model->getSelectString (this);
   798 	else
   799 		return QString();
   800 }
   801 
   802 void BranchObj::setAnimation(const AnimPoint &ap)
   803 {
   804 	anim=ap;
   805 }
   806 
   807 bool BranchObj::animate()
   808 {
   809 	anim.animate ();
   810 	if ( anim.isAnimated() )
   811 	{
   812 		setRelPos (anim);
   813 		return true;
   814 	}
   815 	parObj->reposition();	// we might have been relinked meanwhile
   816 	return false;
   817 }
   818