diff -r 000000000000 -r 5c5b4464b24f linkablemapobj.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linkablemapobj.cpp Fri Mar 05 20:16:46 2010 +0000 @@ -0,0 +1,693 @@ +//#include + +#include "linkablemapobj.h" +#include "branchobj.h" +#include "mapeditor.h" + +#include "version.h" + + +///////////////////////////////////////////////////////////////// +// LinkableMapObj +///////////////////////////////////////////////////////////////// + +LinkableMapObj::LinkableMapObj():MapObj() +{ + // cout << "Const LinkableMapObj ()\n"; + init (); +} + +LinkableMapObj::LinkableMapObj(QCanvas* c) :MapObj(c) +{ +// cout << "Const LinkableMapObj\n"; + init (); +} + +LinkableMapObj::LinkableMapObj (LinkableMapObj* lmo) : MapObj (lmo->canvas) +{ + copy (lmo); +} + +LinkableMapObj::~LinkableMapObj() +{ + delete (bottomline); + delete (selbox); + delete (frame); + delLink(); +} + +void LinkableMapObj::delLink() +{ + switch (style) + { + case StyleLine: + delete (l); + break; + case StyleParabel: + segment.clear(); + break; + case StylePolyLine: + delete (p); + delete (l); + break; + case StylePolyParabel: + delete (p); + segment.clear(); + break; + default: + break; + } +} + +void LinkableMapObj::init () +{ + depth=-1; + childObj=NULL; + parObj=NULL; + parObjTmpBuf=NULL; + parPos=QPoint(0,0); + childPos=QPoint(0,0); + link2ParPos=false; + l=NULL; + orientation=OrientUndef; + linkwidth=20; + thickness_start=8; + style=StyleUndef; + linkpos=LinkBottom; + segment.setAutoDelete (TRUE); + arcsegs=13; + QPointArray pa(arcsegs*2+2); + + bottomline=new QCanvasLine(canvas); + bottomline->setPen( QPen(linkcolor, 1) ); + bottomline->setZ(Z_LINK); + bottomline->show(); + + // Prepare showing the selection of a MapObj + selbox = new QCanvasRectangle (canvas); + selbox->setZ(Z_SELBOX); + selbox->setBrush( QColor(255,255,0) ); + selbox->setPen( QPen(QColor(255,255,0) )); + selbox->hide(); + selected=false; + + // initialize frame + frame = new FrameObj (canvas); + + repositionRequest=false; +} + +void LinkableMapObj::copy (LinkableMapObj* other) +{ + MapObj::copy(other); + bboxTotal=other->bboxTotal; +// linkwidth=other->linkwidth; + + setLinkStyle(other->style); + setLinkColor (other->linkcolor); +} + +void LinkableMapObj::setChildObj(LinkableMapObj* o) +{ + childObj=o; +} + +void LinkableMapObj::setParObj(LinkableMapObj* o) +{ + parObj=o; + mapEditor=parObj->getMapEditor(); +} + +void LinkableMapObj::setParObjTmp(LinkableMapObj*,QPoint,int) +{ +} + +void LinkableMapObj::unsetParObjTmp() +{ +} + +LinkStyle LinkableMapObj::getDefLinkStyle () +{ + LinkStyle ls=mapEditor->getLinkStyle(); + switch (ls) + { + case StyleLine: + return ls; + break; + case StyleParabel: + return ls; + break; + case StylePolyLine: + if (depth>1) + return StyleLine; + else + return ls; + break; + case StylePolyParabel: + if (depth>1) + return StyleParabel; + else + return ls; + break; + default: + break; + } + return StyleUndef; +} + +void LinkableMapObj::setLinkStyle(LinkStyle newstyle) +{ + delLink(); + + style=newstyle; + + if (childObj!=NULL && parObj != NULL) + { + int i; + QCanvasLine* cl; + switch (style) + { + case StyleUndef: + bottomline->hide(); + break; + case StyleLine: + l = new QCanvasLine(canvas); + l->setPen( QPen(linkcolor, 1) ); + l->setZ(Z_LINK); + if (visible) + l->show(); + else + l->hide(); + break; + case StyleParabel: + for (i=0;isetPen( QPen(linkcolor, 1) ); + cl->setPoints( 0,0,i*10,100); + cl->setZ(Z_LINK); + if (visible) + cl->show(); + else + cl->hide(); + segment.append(cl); + } + pa0.resize (arcsegs+1); + break; + case StylePolyLine: + p = new QCanvasPolygon(canvas); + p->setBrush( linkcolor ); + p->setZ(Z_LINK); + if (visible) + p->show(); + else + p->hide(); + pa0.resize (3); + // TODO + // a bit awkward: draw the lines additionally to polygon, to avoid + // missing pixels, when polygon is extremly flat + l = new QCanvasLine(canvas); + l->setPen( QPen(linkcolor, 1) ); + l->setZ(Z_LINK); + if (visible) + l->show(); + else + l->hide(); + break; + case StylePolyParabel: + p = new QCanvasPolygon(canvas); + p->setBrush( linkcolor ); + p->setZ(Z_LINK); + if (visible) + p->show(); + else + p->hide(); + pa0.resize (arcsegs*2+2); + pa1.resize (arcsegs+1); + pa2.resize (arcsegs+1); + + // TODO + // a bit awkward: draw the lines additionally + // to polygon, to avoid missing pixels, + // if polygon is extremly flat + for (i=0;isetPen( QPen(linkcolor, 1) ); + cl->setPoints( 0,0,i*10,100); + cl->setZ(Z_LINK); + if (visible) + cl->show(); + else + cl->hide(); + segment.append(cl); + } + break; + default: + break; + } + } else + { + cout << "Error: ChildObj or parObj == NULL in LinkableMapObj::setLinkStyle\n"; + } +} + +LinkStyle LinkableMapObj::getLinkStyle() +{ + return style; +} + +void LinkableMapObj::setLinkPos(LinkPos lp) +{ + linkpos=lp; +} + +LinkPos LinkableMapObj::getLinkPos() +{ + return linkpos; +} + + +void LinkableMapObj::setLinkColor() +{ + // Overloaded in BranchObj and childs + // here only set default color + setLinkColor (mapEditor->getDefLinkColor()); +} + +void LinkableMapObj::setLinkColor(QColor col) +{ + linkcolor=col; + bottomline->setPen( QPen(linkcolor, 1) ); + QCanvasLine *cl; + switch (style) + { + case StyleLine: + l->setPen( QPen(col,1)); + break; + case StyleParabel: + for (cl=segment.first(); cl; cl=segment.next() ) + cl->setPen( QPen(col,1)); + break; + case StylePolyLine: + p->setBrush( QBrush(col)); + l->setPen( QPen(col,1)); + break; + case StylePolyParabel: + p->setBrush( QBrush(col)); + for (cl=segment.first(); cl; cl=segment.next() ) + cl->setPen( QPen(col,1)); + break; + default: + break; + } // switch (style) + updateLink(); +} + +QColor LinkableMapObj::getLinkColor() +{ + return linkcolor; +} + +FrameType LinkableMapObj::getFrameType() +{ + return frame->getFrameType(); +} + +void LinkableMapObj::setFrameType(const FrameType &t) +{ + frame->setFrameType(t); + calcBBoxSize(); + positionBBox(); + requestReposition(); +} + +void LinkableMapObj::setFrameType(const QString &t) +{ + frame->setFrameType(t); + calcBBoxSize(); + positionBBox(); + requestReposition(); +} + +void LinkableMapObj::setVisibility (bool v) +{ + MapObj::setVisibility (v); + if (visible) + { + bottomline->show(); + // FIXME lines and segments should be done in LMO? + if (style==StyleLine && l) + { + l->show(); + } else + { + QCanvasLine* cl; + for (cl=segment.first(); cl; cl=segment.next() ) + cl->show(); + } + } else + { + bottomline->hide(); + if (style==StyleLine && l) + { + l->hide(); + } else + { + QCanvasLine* cl; + for (cl=segment.first(); cl; cl=segment.next() ) + cl->hide(); + } + } +} + +void LinkableMapObj::updateLink() +{ + // needs: + // childPos of parent + // orient of parent + // style + // + // sets: + // orientation + // childPos + // parPos + // offset + // drawing of the link itself + + + // updateLink is called from move, but called from constructor we don't + // have parents yet... + if (style==StyleUndef) return; + + if (frame->getFrameType() == NoFrame) + linkpos=LinkBottom; + else + linkpos=LinkMiddle; + switch (linkpos) + { + case LinkMiddle: + offset=bbox.height() /2; + break; + default : + offset=bbox.height()-1; // draw link to bottom of bbox + break; + } + + double p2x,p2y; // Set P2 Before setting + if (!link2ParPos) + { + p2x=QPoint( parObj->getChildPos() ).x(); // P1, we have to look at + p2y=QPoint( parObj->getChildPos() ).y(); // orientation + } else + { + p2x=QPoint( parObj->getParPos() ).x(); + p2y=QPoint( parObj->getParPos() ).y(); + } + + LinkOrient orientOld=orientation; + + // Set orientation, first look for orientation of parent + if (parObj->getOrientation() != OrientUndef ) + // use the orientation of the parent: + orientation=parObj->getOrientation(); + else + { + // calc orientation depending on position rel to mapCenter + if (absPos.x() < QPoint(parObj->getChildPos() ).x() ) + orientation=OrientLeftOfCenter; + else + orientation=OrientRightOfCenter; + } + + if ((orientation!=orientOld) && (orientOld!= OrientUndef)) + { + // Orientation just changed. Reorient this subbranch, because move is called + // before updateLink => Position is still the old one, which could lead to + // linking of subranch to itself => segfault + // + // Also possible: called in BranchObj::init(), then orientOld==OrientUndef, + // no need to reposition now + reposition(); + } + + if (orientation==OrientLeftOfCenter ) + { + childPos=QPoint (absPos.x(),absPos.y()+offset); + parPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset ); + } else + { + childPos=QPoint (absPos.x()+ bbox.width(), absPos.y() + offset ); + parPos=QPoint (absPos.x(),absPos.y()+offset); + } + /* FIXME + cout << " LMO::updateLink absPos="<setPoints( lrint (parPos.x()), + lrint(parPos.y()), + lrint(p2x), + lrint(p2y) ); + break; + case StyleParabel: + parabel (pa0, p1x,p1y,p2x,p2y); + i=0; + for (cl=segment.first(); cl; cl=segment.next() ) + { + cl->setPoints( pa0.point(i).x(), pa0.point(i).y(),pa0.point(i+1).x(),pa0.point(i+1).y()); + i++; + } + break; + case StylePolyLine: + pa0[0]=QPoint (lrint(p2x+tp.x()), lrint(p2y+tp.y())); + pa0[1]=QPoint (lrint(p2x-tp.x()), lrint(p2y-tp.y())); + pa0[2]=QPoint (lrint (parPos.x()), lrint(parPos.y()) ); + p->setPoints (pa0); + // here too, draw line to avoid missing pixels + l->setPoints( lrint (parPos.x()), + lrint(parPos.y()), + lrint(p2x), + lrint(p2y) ); + break; + case StylePolyParabel: + parabel (pa1, p1x,p1y,p2x+tp.x(),p2y+tp.y()); + parabel (pa2, p1x,p1y,p2x-tp.x(),p2y-tp.y()); + for (i=0;i<=arcsegs;i++) + { + // Combine the arrays to a single one + pa0[i]=pa1[i]; + pa0[i+arcsegs+1]=pa2[arcsegs-i]; + } + p->setPoints (pa0); + i=0; + for (cl=segment.first(); cl; cl=segment.next() ) + { + cl->setPoints( pa1.point(i).x(), pa1.point(i).y(),pa1.point(i+1).x(),pa1.point(i+1).y()); + i++; + } + break; + default: + break; + } // switch (style) +} + +LinkableMapObj* LinkableMapObj::getChildObj() +{ + return childObj; +} + +LinkableMapObj* LinkableMapObj::getParObj() +{ + return parObj; +} + +QPoint LinkableMapObj::getChildPos() +{ + return childPos; +} + +QPoint LinkableMapObj::getParPos() +{ + return parPos; +} + +QPoint LinkableMapObj::getRelPos() +{ + if (!parObj) return QPoint (0,0); + return QPoint( + absPos.x() - parObj->x(), + absPos.y() - parObj->y() + ); +} + +LinkOrient LinkableMapObj::getOrientation() +{ + return orientation; +} + +int LinkableMapObj::getDepth() +{ + return depth; +} + +void LinkableMapObj::setMapEditor (MapEditor *me) +{ + mapEditor=me; +} + +MapEditor* LinkableMapObj::getMapEditor () +{ + return mapEditor; +} + +QPoint LinkableMapObj::getRandPos() +{ + // Choose a random position with given distance to parent: + double a=rand()%360 * 2 * M_PI / 360; + return QPoint ( (int)( + 150*cos (a)), + (int)( + 150*sin (a))); +} + +void LinkableMapObj::alignRelativeTo (QPoint ref) +{ +} + +void LinkableMapObj::reposition() +{ +cout << "LMO::reposition ???"<requestReposition(); + } +} + +void LinkableMapObj::forceReposition() +{ + // Sometimes a reposition has to be done immediatly: For example + // if the note editor flag changes, there is no user event in mapeditor + // which could collect requests for a reposition. + // Then we have to call forceReposition() + // But no rule without exception: While loading a map or undoing it, + // we want to block expensive repositioning, but just do it once at + // the end, thus check first: + + if (mapEditor->blockReposition()) return; + + // Pass on the request to parental objects, if this hasn't been done yet + + if (parObj) + parObj->forceReposition(); + else + reposition(); } + +bool LinkableMapObj::repositionRequested() +{ + return repositionRequest; +} + + +void LinkableMapObj::setSelBox() +{ + selbox->setX (bbox.x() ); + selbox->setY (bbox.y() ); + selbox->setSize (bbox.width(), bbox.height() ); +} + +void LinkableMapObj::select() +{ + setSelBox(); + selected=true; + selbox->show(); +} + + +void LinkableMapObj::unselect() +{ + selected=false; + selbox->hide(); +} + +void LinkableMapObj::parabel (QPointArray &ya, double p1x, double p1y, double p2x, double p2y) + +{ + double vx=p2x - p1x; // V=P2-P1 + double vy=p2y - p1y; + + double dx; // delta x during calculation of parabel + + double pnx; // next point + double pny; + double m; + + if (vx > -0.0001 && vx < 0.0001) + m=0; + else + m=(vy / (vx*vx)); + dx=vx/(arcsegs); + int i; + ya.setPoint (0,QPoint (lrint(p1x),lrint(p1y))); + for (i=1;i<=arcsegs;i++) + { + pnx=p1x+dx; + pny=m*(pnx-parPos.x())*(pnx-parPos.x())+parPos.y(); + ya.setPoint (i,QPoint (lrint(pnx),lrint(pny))); + p1x=pnx; + p1y=pny; + } +} +