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