X-Git-Url: https://git.sven.stormbind.net/?a=blobdiff_plain;f=src%2Flinkablemapobj.cpp;fp=src%2Flinkablemapobj.cpp;h=ee9bd7c541b919c20b0acd9e40b27667dbc9e2f4;hb=d483bd8e6523c23c6f1d8908a2e0611c2bc9ff4f;hp=0000000000000000000000000000000000000000;hpb=7dfa3fe589d1722d49681f42cdb0bf1e6efb5223;p=sven%2Fvym.git diff --git a/src/linkablemapobj.cpp b/src/linkablemapobj.cpp new file mode 100644 index 0000000..ee9bd7c --- /dev/null +++ b/src/linkablemapobj.cpp @@ -0,0 +1,595 @@ +#include +#include +#include + +#include "branchobj.h" +#include "linkablemapobj.h" +#include "vymmodel.h" + +extern bool debug; + +///////////////////////////////////////////////////////////////// +// LinkableMapObj +///////////////////////////////////////////////////////////////// + +LinkableMapObj::LinkableMapObj(QGraphicsItem *parent, TreeItem *ti) + : MapObj(parent, ti) +{ + // qDebug() << "Const LinkableMapObj this="<getMapLinkStyle(); + int depth = 1 + parent->depth(); + if (depth == 0) + return UndefinedStyle; + switch (ls) { + case Line: + return ls; + break; + case Parabel: + return ls; + break; + case PolyLine: + if (depth > 1) + return Line; + else + return ls; + break; + case PolyParabel: + if (depth > 1) + return Parabel; + else + return ls; + break; + default: + break; + } + return UndefinedStyle; +} + +void LinkableMapObj::setLinkStyle(Style newstyle) +{ + // qDebug()<<"LMO::setLinkStyle s="<getHeading()<<" parObj="<addLine(QLineF(1, 1, 1, 1), pen); + l->setZValue(dZ_LINK); + if (visible) + l->show(); + else + l->hide(); + createBottomLine(); + break; + case Parabel: + for (int i = 0; i < arcsegs; i++) { + cl = scene()->addLine(QLineF(i * 5, 0, i * 10, 100), pen); + cl->setZValue(dZ_LINK); + if (visible) + cl->show(); + else + cl->hide(); + segment.append(cl); + } + pa0.resize(arcsegs + 1); + createBottomLine(); + break; + case PolyLine: + p = scene()->addPolygon(QPolygonF(), pen, linkcolor); + p->setZValue(dZ_LINK); + if (visible) + p->show(); + else + p->hide(); + pa0.resize(3); + createBottomLine(); + break; + case PolyParabel: + p = scene()->addPolygon(QPolygonF(), pen, linkcolor); + p->setZValue(dZ_LINK); + if (visible) + p->show(); + else + p->hide(); + pa0.resize(arcsegs * 2 + 2); + pa1.resize(arcsegs + 1); + pa2.resize(arcsegs + 1); + createBottomLine(); + break; + default: + break; + } +} + +LinkableMapObj::Style LinkableMapObj::getLinkStyle() { return style; } + +void LinkableMapObj::setLinkPos(Position lp) { linkpos = lp; } + +LinkableMapObj::Position LinkableMapObj::getLinkPos() { return linkpos; } + +void LinkableMapObj::setLinkColor() +{ + // Overloaded in BranchObj and children + // here only set default color + VymModel *model = treeItem->getModel(); + if (!model) + return; + + if (model->getMapLinkColorHint() == HeadingColor) { + if (treeItem->isBranchLikeType() ) + LinkableMapObj::setLinkColor(treeItem->getHeading().getColor()); + else + // For images use color of parent heading + LinkableMapObj::setLinkColor(treeItem->parent()->getHeading().getColor()); + } else + LinkableMapObj::setLinkColor(model->getMapDefLinkColor()); +} + +void LinkableMapObj::setLinkColor(QColor col) +{ + linkcolor = col; + pen.setColor(col); + if (bottomline) + bottomline->setPen(pen); + switch (style) { + case Line: + l->setPen(pen); + break; + case Parabel: + for (int i = 0; i < segment.size(); ++i) + segment.at(i)->setPen(pen); + break; + case PolyLine: + p->setBrush(QBrush(col)); + p->setPen(pen); + break; + case PolyParabel: + p->setBrush(QBrush(col)); + p->setPen(pen); + break; + default: + break; + } +} + +QColor LinkableMapObj::getLinkColor() { return linkcolor; } + +void LinkableMapObj::setVisibility(bool v) +{ + MapObj::setVisibility(v); + updateVisibility(); +} + +void LinkableMapObj::setOrientation() +{ + if (!parObj) { + orientation = UndefinedOrientation; + return; + } + + // calc orientation depending on position rel to parent + if (useRelPos) { + if (relPos.x() < 0) + orientation = LeftOfCenter; + else + orientation = RightOfCenter; + } + else + // use the orientation of the parent: + orientation = parObj->getOrientation(); +} + +void LinkableMapObj::updateVisibility() +{ + bool visnow = visible; + + // Hide links of unselected objects (if wanted) + if (((MapItem *)treeItem)->getHideLinkUnselected() && + !treeItem->getModel()->isSelected(treeItem)) + visnow = false; + + if (visnow) { + if (bottomline) { + if (useBottomline) + bottomline->show(); + else + bottomline->hide(); + } + + switch (style) { + case Line: + if (l) + l->show(); + break; + case Parabel: + for (int i = 0; i < segment.size(); ++i) + segment.at(i)->show(); + break; + case PolyLine: + if (p) + p->show(); + else + qDebug() << "LMO::updateVis p==0 (PolyLine)"; // FIXME-4 + break; + case PolyParabel: + if (p) + p->show(); + else + qDebug() << "LMO::updateVis p==0 (PolyParabel) " + << treeItem->getHeadingPlain(); // FIXME-4 + break; + default: + break; + } + } + else { + if (bottomline) + bottomline->hide(); + switch (style) { + case Line: + if (l) + l->hide(); + break; + case Parabel: + for (int i = 0; i < segment.size(); ++i) + segment.at(i)->hide(); + break; + case PolyLine: + if (p) + p->hide(); + break; + case PolyParabel: + if (p) + p->hide(); + break; + default: + break; + } + } +} + +void LinkableMapObj::updateLinkGeometry() +{ + // needs: + // childRefPos of parent + // orient of parent + // style + // + // sets: + // orientation + // childRefPos (by calling setDockPos()) + // parPos (by calling setDockPos()) + // bottomlineY + // drawing of the link itself + + // updateLinkGeometry is called from move, but called from constructor we + // don't have parents yet... + + if (style == UndefinedStyle) { + setDockPos(); + return; + } + + switch (linkpos) { + case Middle: + bottomlineY = + bbox.top() + bbox.height() / 2; // draw link to middle (of frame) + break; + case Bottom: + // bottomlineY = bbox.bottom()-1; // draw link to bottom of box + bottomlineY = bbox.bottom() - botPad; + break; + } + + double p2x, p2y; // Set P2 Before setting + if (!link2ParPos) { + p2x = QPointF(parObj->getChildRefPos()).x(); // P1, we have to look at + p2y = QPointF(parObj->getChildRefPos()).y(); // orientation + } + else { + p2x = QPointF(parObj->getParPos()).x(); + p2y = QPointF(parObj->getParPos()).y(); + } + + setOrientation(); + setDockPos(); // Call overloaded method + + double p1x = parPos.x(); // Link is drawn from P1 to P2 + double p1y = parPos.y(); + + double vx = p2x - p1x; // V=P2-P1 + double vy = p2y - p1y; + + int z; + // Hack to z-move links to MapCenter (d==1) below MCOs frame (d==0) + // //FIXME-4 no longer used? + if (treeItem->depth() < 2) + // z=(treeItem->depth() -2)*dZ_DEPTH + dZ_LINK; + z = -dZ_LINK; + else + z = dZ_LINK; + + // qDebug()<<"LMO::updateGeo d="<depth()<<" this="<getHeading(); + + // Draw the horizontal line below heading (from childRefPos to ParPos) + if (bottomline) { + bottomline->setLine(QLineF(childRefPos.x(), childRefPos.y(), p1x, p1y)); + bottomline->setZValue(z); + } + + double a; // angle + if (vx > -0.000001 && vx < 0.000001) + a = M_PI_2; + else + a = atan(vy / vx); + // "turning point" for drawing polygonal links + QPointF tp(-qRound(sin(a) * thickness_start), + qRound(cos(a) * thickness_start)); + + // Draw the link + switch (style) { + case Line: + l->setLine(QLine(qRound(parPos.x()), qRound(parPos.y()), qRound(p2x), + qRound(p2y))); + l->setZValue(z); + break; + case Parabel: + parabel(pa0, p1x, p1y, p2x, p2y); + for (int i = 0; i < segment.size(); ++i) { + segment.at(i)->setLine(QLineF(pa0.at(i).x(), pa0.at(i).y(), + pa0.at(i + 1).x(), + pa0.at(i + 1).y())); + segment.at(i)->setZValue(z); + } + break; + case PolyLine: + pa0.clear(); + pa0 << QPointF(qRound(p2x + tp.x()), qRound(p2y + tp.y())); + pa0 << QPointF(qRound(p2x - tp.x()), qRound(p2y - tp.y())); + pa0 << QPointF(qRound(parPos.x()), qRound(parPos.y())); + p->setPolygon(QPolygonF(pa0)); + p->setZValue(z); + break; + case PolyParabel: + parabel(pa1, p1x, p1y, p2x + tp.x(), p2y + tp.y()); + parabel(pa2, p1x, p1y, p2x - tp.x(), p2y - tp.y()); + pa0.clear(); + for (int i = 0; i <= arcsegs; i++) + pa0 << QPointF(pa1.at(i)); + for (int i = 0; i <= arcsegs; i++) + pa0 << QPointF(pa2.at(arcsegs - i)); + p->setPolygon(QPolygonF(pa0)); + p->setZValue(z); + break; + default: + break; + } +} + +QPointF LinkableMapObj::getChildRefPos() { return childRefPos; } + +QPointF LinkableMapObj::getFloatRefPos() { return floatRefPos; } + +QPointF LinkableMapObj::getParPos() { return parPos; } + +LinkableMapObj::Orientation LinkableMapObj::getOrientation() +{ + return orientation; +} + +void LinkableMapObj::reposition() // virtual +{ +} + +void LinkableMapObj::requestReposition() +{ + if (!repositionRequest) { + // Pass on the request to parental objects, if this hasn't + // been done yet + repositionRequest = true; + if (parObj) + parObj->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: + + VymModel *model = treeItem->getModel(); + if (model->isRepositionBlocked()) + return; + + // Pass on the request to parent objects, if this hasn't been done yet + if (parObj) + parObj->forceReposition(); + else + reposition(); +} + +bool LinkableMapObj::repositionRequested() { return repositionRequest; } + +void LinkableMapObj::parabel(QPolygonF &ya, qreal p1x, qreal p1y, qreal p2x, + qreal p2y) + +{ + qreal vx = p2x - p1x; // V=P2-P1 + qreal vy = p2y - p1y; + + qreal dx; // delta x during calculation of parabel + + qreal pnx; // next point + qreal pny; + qreal m; + + if (vx > -0.0001 && vx < 0.0001) + m = 0; + else + m = (vy / (vx * vx)); + dx = vx / (arcsegs); + ya.clear(); + ya << QPointF(p1x, p1y); + for (int i = 1; i <= arcsegs; i++) { + pnx = p1x + dx; + pny = m * (pnx - parPos.x()) * (pnx - parPos.x()) + parPos.y(); + ya << QPointF(pnx, pny); + p1x = pnx; + p1y = pny; + } +}