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