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