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