# HG changeset patch
# User insilmaril
# Date 1252673775 0
# Node ID d922fb6ea482a7c13fb9e6ba9c5f5082a7432e1e
# Parent  cac93797c58032dca1bb0661fdf2858c067fa420
more fixes for collisions

diff -r cac93797c580 -r d922fb6ea482 branchobj.cpp
--- a/branchobj.cpp	Wed Sep 09 12:57:06 2009 +0000
+++ b/branchobj.cpp	Fri Sep 11 12:56:15 2009 +0000
@@ -3,7 +3,7 @@
 #include "branchitem.h"
 #include "geometry.h"
 #include "mapeditor.h"
-#include "mainwindow.h"
+#include "mainwindow.h"   
 #include "misc.h"
 
 extern FlagRow *standardFlagsMaster;
@@ -16,9 +16,13 @@
 BranchObj::BranchObj (QGraphicsScene* s,TreeItem *ti):OrnamentedObj (s)
 {
 //    cout << "Const BranchObj (s)  \n";
-	parObj=NULL;
     scene=s;
 	treeItem=ti;
+	BranchItem *pi=(BranchItem*)(ti->parent());
+	if (pi && pi!=ti->getModel()->getRootItem() )
+		parObj=pi->getLMO();
+	else
+		parObj=NULL;
 	init();
 }
 
@@ -715,14 +719,28 @@
 
 ConvexPolygon BranchObj::getBoundingPolygon()
 {
-	if (treeItem->branchCount()==0)
+/*
+	if (!pi)	//FIXME-3 Testing only
+	{
+		pi=scene->addPolygon(MapObj::getBoundingPolygon() );
+		pi->setPen(Qt::NoPen);
+		pi->setBrush( QColor(qrand()%32*8,qrand()%32*8,qrand()%32*8) );
+		pi->setZValue(Z_BBOX);
+	}
+	*/
+	if (treeItem->branchCount()==0 || treeItem->depth()==0)
+	{
+		if (pi) pi->setPolygon (MapObj::getBoundingPolygon() );
 		return MapObj::getBoundingPolygon();
+	}
 
+	calcBBoxSizeWithChildren();	//FIXME-3 really needed?
 	QPolygonF p;
 	p<<bboxTotal.topLeft();
 	p<<bboxTotal.topRight();
 	p<<bboxTotal.bottomRight();
 	p<<bboxTotal.bottomLeft();
+		if (pi) pi->setPolygon (p );
 	return p;
 }
 
diff -r cac93797c580 -r d922fb6ea482 mapeditor.cpp
--- a/mapeditor.cpp	Wed Sep 09 12:57:06 2009 +0000
+++ b/mapeditor.cpp	Fri Sep 11 12:56:15 2009 +0000
@@ -560,7 +560,7 @@
 void MapEditor::testFunction2()
 {
 	// Create list with all bounding polygons
-	QList <MapObj*> mapobjects;
+	QList <LinkableMapObj*> mapobjects;
 	QList <ConvexPolygon> polys; 
 	ConvexPolygon p;
 	QList <Vector> vectors;
@@ -570,25 +570,16 @@
 	BranchItem *bi;
 	BranchItem *bi2;
 	BranchObj *bo;
-	BranchItem *ri=model->getRootItem();
-	for (int i=0;i<ri->branchCount();++i)
+
+	// Outer loop: Iterate until we no more changes in orientation 
+	bool orientationChanged=true;
+	while (orientationChanged)
 	{
-		bi=ri->getBranchNum (i);
-		bo=(BranchObj*)bi->getLMO();
-		if (bo)
+		BranchItem *ri=model->getRootItem();
+		for (int i=0;i<ri->branchCount();++i)
 		{
-			mapobjects.append (bo);
-			p=bo->getBoundingPolygon();
-			p.calcCentroid();
-			polys.append(p);
-			vectors.append (QPointF(0,0));
-			orgpos.append (p.at(0));
-			headings.append (bi->getHeading());
-		}
-		for (int j=0;j<bi->branchCount();++j)
-		{
-			bi2=bi->getBranchNum (j);
-			bo=(BranchObj*)bi2->getLMO();
+			bi=ri->getBranchNum (i);
+			bo=(BranchObj*)bi->getLMO();
 			if (bo)
 			{
 				mapobjects.append (bo);
@@ -597,57 +588,85 @@
 				polys.append(p);
 				vectors.append (QPointF(0,0));
 				orgpos.append (p.at(0));
-				headings.append (bi2->getHeading());
-			}	
-		}
-	}
-
-	// Iterate moving bounding polygons until we have no more collisions
-	int collisions=1;
-	while (collisions>0)
-	{
-		collisions=0;
-		for (int i=0; i<polys.size()-1; ++i)
-		{
-			for (int j=i+1; j<polys.size();++j)
+				headings.append (bi->getHeading());
+			}
+			for (int j=0;j<bi->branchCount();++j)
 			{
-				if (polygonCollision (polys.at(i),polys.at(j), QPointF(0,0)).intersect )
+				bi2=bi->getBranchNum (j);
+				bo=(BranchObj*)bi2->getLMO();
+				if (bo)
 				{
-					collisions++;
-					v=polys.at(j).centroid()-polys.at(i).centroid();
-					// Move also away if centroids are identical
-					if (v.isNull()) 
-					{
-						//cout << "v==0="<<polys[i].centroid()<<polys[j].centroid()<<" "<<v<<"  "<<headings[i].toStdString()<<" - "<<headings[j].toStdString()<<"  ";
-						v.setX (rand()%200 -100);
-						v.setY (rand()%200 -100);
-						//cout << v;
-					}
-					v.normalize();
-					v.scale (2);
-					//cout <<  "  "<<v<<endl;
-					vectors[j]=v;
-					vectors[i]=v;
-					vectors[i].invert();
-				}  
+					mapobjects.append (bo);
+					p=bo->getBoundingPolygon();
+					p.calcCentroid();
+					polys.append(p);
+					vectors.append (QPointF(0,0));
+					orgpos.append (p.at(0));
+					headings.append (bi2->getHeading());
+				}	
 			}
 		}
-		for (int i=0;i<vectors.size();i++)
+
+		// Iterate moving bounding polygons until we have no more collisions
+		int collisions=1;
+		while (collisions>0)
 		{
-			//cout << " v="<<vectors[i]<<" "<<headings[i].toStdString()<<endl;
-			polys[i].translate (vectors[i]);
-		}
-		//cout << "Collisions: "<<collisions<<endl;
-		//collisions=0;
-	}	
+			collisions=0;
+			for (int i=0; i<polys.size()-1; ++i)
+			{
+				for (int j=i+1; j<polys.size();++j)
+				{
+					if (polygonCollision (polys.at(i),polys.at(j), QPointF(0,0)).intersect )
+					{
+						collisions++;
+						//cout << "Collision: "<<headings[i].toStdString()<<" - "<<headings[j].toStdString()<<endl;
+						v=polys.at(j).centroid()-polys.at(i).centroid();
+						// Move also away if centroids are identical
+						if (v.isNull()) 
+						{
+							//cout << "v==0="<<polys[i].centroid()<<polys[j].centroid()<<" "<<v<<endl;
+							v.setX (rand()%200 -100);
+							v.setY (rand()%200 -100);
+							//cout << v;
+						}
+						v.normalize();
+						v.scale (2);
+						//cout <<  "  v="<<v<<endl;
+						vectors[j]=v;
+						vectors[i]=v;
+						vectors[i].invert();
+					}  
+				}
+			}
+			for (int i=0;i<vectors.size();i++)
+			{
+				//cout << " v="<<vectors[i]<<" "<<headings[i].toStdString()<<endl;
+				polys[i].translate (vectors[i]);
+			}
+			cout << "Collisions: "<<collisions<<endl;
+			//collisions=0;
+		}	
 
-	// Finally move the real objects and update 
-	for (int i=0;i<polys.size();i++)
-	{
-		Vector v=polys[i].at(0)-orgpos[i];
-		mapobjects[i]->moveBy(v.x(),v.y() );
-	}	
-	model->reposition();	
+		// Finally move the real objects and update 
+		QList <LinkableMapObj::Orientation> orients;
+		for (int i=0;i<polys.size();i++)
+		{
+			Vector v=polys[i].at(0)-orgpos[i];
+			orients.append (mapobjects[i]->getOrientation());
+			mapobjects[i]->moveBy(v.x(),v.y() );
+		}	
+		model->reposition();	
+		orientationChanged=false;
+		for (int i=0;i<polys.size();i++)
+			if (orients[i]!=mapobjects[i]->getOrientation())
+			{
+				orientationChanged=true;
+				break;
+			}
+		cout << "Final: orientChanged="<<orientationChanged<<endl;
+		break;
+		//orientationChanged=false;
+	} // loop if orientation has changed
 }
 
 BranchItem* MapEditor::getBranchDirectAbove (BranchItem *bi)
@@ -1190,6 +1209,7 @@
 					lmosel->setRelPos();	
 				} 
 
+			} // depth>0
 				// Maybe we can relink temporary?
 				if (dsti)
 				{
@@ -1208,7 +1228,6 @@
 				}		
 				// reposition subbranch
 				lmosel->reposition();	
-			} // depth>0
 
 			QItemSelection sel=model->getSelectionModel()->selection();
 			updateSelection(sel,sel);	// position has changed
@@ -1278,7 +1297,11 @@
 			tmpXLink->setEnd ( ((BranchItem*)dsti) );
 			tmpXLink->updateXLink();
 			tmpXLink->activate(); 
-			//FIXME-0 model->saveStateComplete(QString("Activate xLink from %1 to %2").arg(model->getObjectName(tmpXLink->getBegin())).arg(model->getObjectName(tmpXLink->getEnd())) );	
+			model->saveState(
+				tmpXLink,QString("delete ()"),
+				dsti,QString("addXLink (\"%1\",\"%2\")").arg(model->getSelectString(tmpXLink->getBegin())).arg(model->getSelectString(dsti)),
+				QString("Add xLink from %1 to %2").arg(model->getObjectName(tmpXLink->getBegin())).arg(model->getObjectName(dsti)) 
+			);	
 		} else
 		{
 			model->deleteItem(tmpXLink);
diff -r cac93797c580 -r d922fb6ea482 mapobj.cpp
--- a/mapobj.cpp	Wed Sep 09 12:57:06 2009 +0000
+++ b/mapobj.cpp	Fri Sep 11 12:56:15 2009 +0000
@@ -36,6 +36,7 @@
 {
     absPos=QPointF(0,0);
     visible=true;
+	pi=NULL;
 }
 
 void MapObj::copy(MapObj* other)
diff -r cac93797c580 -r d922fb6ea482 mapobj.h
--- a/mapobj.h	Wed Sep 09 12:57:06 2009 +0000
+++ b/mapobj.h	Fri Sep 11 12:56:15 2009 +0000
@@ -63,6 +63,7 @@
 
 	TreeItem *treeItem;				//! Crossrefence to treemodel
 
+	QGraphicsPolygonItem *pi;	//FIXME-3 testing only
 };
 
 #endif
diff -r cac93797c580 -r d922fb6ea482 treeitem.cpp
--- a/treeitem.cpp	Wed Sep 09 12:57:06 2009 +0000
+++ b/treeitem.cpp	Fri Sep 11 12:56:15 2009 +0000
@@ -278,9 +278,9 @@
 	{
 		case MapCenter: return childItems.indexOf (item) - branchOffset;
 		case Branch: return childItems.indexOf (item) - branchOffset;
-		case Image: return parentItem->childItems.indexOf (item) - imageOffset;
-		case Attribute: return parentItem->childItems.indexOf (item) - attributeOffset;
-		case XLink: return parentItem->childItems.indexOf (item) - xlinkOffset;
+		case Image: return childItems.indexOf (item) - imageOffset;
+		case Attribute: return childItems.indexOf (item) - attributeOffset;
+		case XLink: return childItems.indexOf (item) - xlinkOffset;
 		default: return -1;
 	}
 }
@@ -601,6 +601,14 @@
 		return NULL;
 }
 
+AttributeItem* TreeItem::getAttributeNum (const int &n)
+{
+	if (n>=0 && n<attributeCounter)
+		return (AttributeItem*)getChildNum (attributeOffset + n);
+	else
+		return NULL;
+}
+
 XLinkItem* TreeItem::getXLinkNum (const int &n)	
 {
 	if (n>=0 && n<xlinkCounter )
diff -r cac93797c580 -r d922fb6ea482 treeitem.h
--- a/treeitem.h	Wed Sep 09 12:57:06 2009 +0000
+++ b/treeitem.h	Fri Sep 11 12:56:15 2009 +0000
@@ -9,11 +9,12 @@
 #include "noteobj.h"
 #include "xmlobj.h"
 
-class LinkableMapObj;
+class AttributeItem;
 class BranchObj;
 class BranchItem;
 class FloatImageObj;
 class ImageItem;
+class LinkableMapObj;
 class VymModel;
 class XLinkItem;
 class XLinkObj;
@@ -21,7 +22,7 @@
 class TreeItem:public XMLObj
 {
 public:
-	enum Type {Undefined,MapCenter,Branch,Image,Attribute,XLink};	//FIXME-3 MapCenter still needed?
+	enum Type {Undefined,MapCenter,Branch,Image,Attribute,XLink};
 	enum HideTmpMode {HideNone, HideExport};
 
     TreeItem();
@@ -155,6 +156,8 @@
 	virtual ImageItem* getImageNum(const int &n);
 	virtual FloatImageObj* getImageObjNum(const int &n);
 
+	virtual AttributeItem* getAttributeNum(const int &n);
+
 	virtual XLinkItem* getXLinkNum(const int &n);
 	virtual XLinkObj* getXLinkObjNum(const int &n);
 
diff -r cac93797c580 -r d922fb6ea482 treemodel.cpp
--- a/treemodel.cpp	Wed Sep 09 12:57:06 2009 +0000
+++ b/treemodel.cpp	Fri Sep 11 12:56:15 2009 +0000
@@ -228,10 +228,14 @@
 bool TreeModel::removeRows ( int row, int count, const QModelIndex & parent)
 {
 	int last=row+count-1;
-    TreeItem *pi= getItem (parent);
+    TreeItem *pi;
+	if (parent.isValid())
+		pi=getItem (parent);
+	else
+		pi=rootItem;
 	TreeItem *ti;
 
-	cout << "TM::removeRows  row="<<row<<"  count="<<count<<endl;
+	cout << "TM::removeRows  pi="<<pi<<"  row="<<row<<"  count="<<count<<endl;
 	for (int i=row; i<=last; i++)
 	{
 		ti=pi->getChildNum (row);
diff -r cac93797c580 -r d922fb6ea482 vymmodel.cpp
--- a/vymmodel.cpp	Wed Sep 09 12:57:06 2009 +0000
+++ b/vymmodel.cpp	Fri Sep 11 12:56:15 2009 +0000
@@ -1135,7 +1135,11 @@
 	QString bakMapDir(QString(tmpMapDir+"/undo-%1").arg(curStep));
 
 	// select  object before undo
-	select (undoSelection);
+	if (!select (undoSelection))
+	{
+		qWarning ("VymModel::undo()  Could not select object for undo");
+		return;
+	}
 
 	if (debug)
 	{
@@ -1424,11 +1428,12 @@
 		parts.removeFirst();
 		if (typ=="mc" || typ=="bo")
 			ti=ti->getBranchNum (n);
-			/* FIXME-2		add other types to getSelectionString and findBy...
-		else
-			if (typ="fi")
-				ti=ti->getImageNum (n);
-				*/
+		else if (typ=="fi")
+			ti=ti->getImageNum (n);
+		else if (typ=="ai")
+			ti=ti->getAttributeNum (n);
+		else if (typ=="xl")
+			ti=ti->getXLinkNum (n);
 		if(!ti) return NULL;		
 	}
 	return  ti;
@@ -2347,7 +2352,12 @@
 			select (pi);
 			reposition();
 			emitShowSelection();
-		}
+		} else if (ti->getType()==TreeItem::XLink)
+		{
+			//FIXME-2 savestate missing
+			deleteItem (ti);
+		} else
+			qWarning ("VymmModel::deleteSelection()  unknown type?!");
 	}
 }
 
@@ -2427,7 +2437,7 @@
 
 TreeItem* VymModel::deleteItem (TreeItem *ti)
 {
-	cout << "VM::deleteItem "<<ti<<endl;
+	cout << "VM::deleteItem "<<ti<<"  "<<getSelectString(ti).toStdString()<<endl;
 	if (ti)
 	{
 		TreeItem *pi=ti->parent();
@@ -2950,6 +2960,34 @@
 		} else
 			parser.setError (Aborted,"Wrong number of parameters");
 	/////////////////////////////////////////////////////////////////////
+	} else if (com==QString("addXLink"))
+	{
+		if (parser.parCount()>1)
+		{
+			s=parser.parString (ok,0);	// begin
+			t=parser.parString (ok,1);	// end
+			BranchItem *begin=(BranchItem*)findBySelectString(s);
+			BranchItem *end=(BranchItem*)findBySelectString(t);
+			if (begin && end)
+			{
+				if (begin->isBranchLikeType() && end->isBranchLikeType())
+				{
+					XLinkItem *xl=createXLink (begin,true);
+					if (xl)
+					{
+						xl->setEnd (end);
+						xl->activate();
+					} else
+						parser.setError (Aborted,"Failed to create xLink");
+				}
+				else
+					parser.setError (Aborted,"begin or end of xLink are not branch or mapcenter");
+				
+			} else
+				parser.setError (Aborted,"Couldn't select begin or end of xLink");
+		} else
+			parser.setError (Aborted,"Need at least 2 parameters for begin and end");
+	/////////////////////////////////////////////////////////////////////
 	} else if (com=="clearFlags")	
 	{
 		if (!selti )
@@ -4306,64 +4344,59 @@
 	return defXLinkWidth;
 }
 
-void VymModel::move(const double &x, const double &y)	// FIXME-3
+void VymModel::move(const double &x, const double &y)
 {
 	int i=x; i=y;
-/*
-	BranchObj *bo = getSelectedBranch();
-	if (bo && 
-		(selectionType()==TreeItem::Branch ||
-		 selectionType()==TreeItem::MapCenter ||
-		 selectionType()==TreeItem::Image
-		))
+	MapItem *seli = (MapItem*)getSelectedItem();
+	if (seli && (seli->isBranchLikeType() || seli->getType()==TreeItem::Image))
 	{
-        QPointF ap(bo->getAbsPos());
-        QPointF to(x, y);
-        if (ap != to)
-        {
-            QString ps=qpointfToString(ap);
-            QString s=getSelectString();
-            saveState(
-                s, "move "+ps, 
-                s, "move "+qpointfToString(to), 
-                QString("Move %1 to %2").arg(getObjectName(bo)).arg(ps));
-            bo->move(x,y);
-            reposition();
-            emitSelectionChanged();
-        }
+		LinkableMapObj *lmo=seli->getLMO();
+		if (lmo)
+		{
+			QPointF ap(lmo->getAbsPos());
+			QPointF to(x, y);
+			if (ap != to)
+			{
+				QString ps=qpointFToString(ap);
+				QString s=getSelectString(seli);
+				saveState(
+					s, "move "+ps, 
+					s, "move "+qpointFToString(to), 
+					QString("Move %1 to %2").arg(getObjectName(seli)).arg(ps));
+				lmo->move(x,y);
+				reposition();
+				emitSelectionChanged();
+			}
+		}
 	}
-*/	
 }
 
-void VymModel::moveRel (const double &x, const double &y)	// FIXME-3
+void VymModel::moveRel (const double &x, const double &y)	
 {
 	int i=x; i=y;
-/*
-	BranchObj *bo = getSelectedBranch();
-	if (bo && 
-		(selectionType()==TreeItem::Branch ||
-		 selectionType()==TreeItem::MapCenter ||
-		 selectionType()==TreeItem::Image
-		))
-	if (bo)
+	MapItem *seli = (MapItem*)getSelectedItem();
+	if (seli && (seli->isBranchLikeType() || seli->getType()==TreeItem::Image))
 	{
-        QPointF rp(bo->getRelPos());
-        QPointF to(x, y);
-        if (rp != to)
-        {
-            QString ps=qpointfToString (bo->getRelPos());
-            QString s=getSelectString(bo);
-            saveState(
-                s, "moveRel "+ps, 
-                s, "moveRel "+qpointfToString(to), 
-                QString("Move %1 to relative position %2").arg(getObjectName(bo)).arg(ps));
-            ((OrnamentedObj*)bo)->move2RelPos (x,y);
-            reposition();
-            bo->updateLinkGeometry();
-            emitSelectionChanged();
-        }
+		LinkableMapObj *lmo=seli->getLMO();
+		if (lmo)
+		{
+			QPointF rp(lmo->getRelPos());
+			QPointF to(x, y);
+			if (rp != to)
+			{
+				QString ps=qpointFToString (lmo->getRelPos());
+				QString s=getSelectString(seli);
+				saveState(
+					s, "moveRel "+ps, 
+					s, "moveRel "+qpointFToString(to), 
+					QString("Move %1 to relative position %2").arg(getObjectName(seli)).arg(ps));
+				((OrnamentedObj*)lmo)->move2RelPos (x,y);
+				reposition();
+				lmo->updateLinkGeometry();
+				emitSelectionChanged();
+			}
+		}	
 	}
-*/	
 }
 
 
@@ -4900,7 +4933,10 @@
 		case TreeItem::Branch: s="bo:";break;
 		case TreeItem::Image: s="fi:";break;
 		case TreeItem::Attribute: s="ai:";break;
-		default:break;
+		case TreeItem::XLink: s="xl:";break;
+		default:
+			s="unknown type in VymModel::getSelectString()";
+			break;
 	}
 	s=  s + QString("%1").arg(ti->num());
 	if (ti->depth() >0)
diff -r cac93797c580 -r d922fb6ea482 vymmodel.h
--- a/vymmodel.h	Wed Sep 09 12:57:06 2009 +0000
+++ b/vymmodel.h	Fri Sep 11 12:56:15 2009 +0000
@@ -190,6 +190,12 @@
 		const QString &comment, 
 		TreeItem *saveSelection);
 	/*! Overloaded for convenience */
+    void saveStateComplete(
+		TreeItem *undoSelection, 
+		TreeItem* redoSelection, 
+		const QString &redoCommand, 
+		const QString &comment);
+	/*! Overloaded for convenience */
     void saveStateChangingPart(
 		TreeItem *undoSelection, 
 		TreeItem* redoSelection,