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