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