X-Git-Url: https://git.sven.stormbind.net/?a=blobdiff_plain;f=src%2Fbranchobj.cpp;fp=src%2Fbranchobj.cpp;h=ffae47b78d130bff307d6a2c803aa80e5d594693;hb=d483bd8e6523c23c6f1d8908a2e0611c2bc9ff4f;hp=0000000000000000000000000000000000000000;hpb=7dfa3fe589d1722d49681f42cdb0bf1e6efb5223;p=sven%2Fvym.git diff --git a/src/branchobj.cpp b/src/branchobj.cpp new file mode 100644 index 0000000..ffae47b --- /dev/null +++ b/src/branchobj.cpp @@ -0,0 +1,672 @@ +#include + +#include "branchobj.h" + +#include "attributeitem.h" +#include "branchitem.h" +#include "geometry.h" +#include "mainwindow.h" +#include "mapeditor.h" +#include "misc.h" + +extern FlagRowMaster *standardFlagsMaster; +extern FlagRowMaster *userFlagsMaster; +extern FlagRowMaster *systemFlagsMaster; +extern bool debug; +extern bool usingDarkTheme; + +///////////////////////////////////////////////////////////////// +// BranchObj +///////////////////////////////////////////////////////////////// + +BranchObj::BranchObj(QGraphicsItem *parent, TreeItem *ti) + : OrnamentedObj(parent, ti) +{ + // qDebug ()<< "Const BranchObj (s,ti) ti="<parent()); + if (pi && pi != ti->getModel()->getRootItem()) + parObj = pi->getLMO(); + else + parObj = NULL; + init(); +} + +BranchObj::~BranchObj() +{ + // qDebug()<< "Destr BranchObj of "<getModel(); + model->stopAnimation(this); + } + + clear(); +} + +void BranchObj::init() +{ + if (parObj) + absPos = parObj->getChildRefPos(); +} + +void BranchObj::copy(BranchObj *other) +{ + OrnamentedObj::copy(other); + + setVisibility(other->visible); + + positionBBox(); +} + +void BranchObj::clear() {} + +void BranchObj::setParObjTmp(LinkableMapObj *dst, QPointF m, int off) +{ + // Temporary link to dst + // m is position of mouse pointer + // offset 0: default 1: below dst -1 above dst (if possible) + + BranchItem *dsti = (BranchItem *)(dst->getTreeItem()); + + BranchItem *pi = (BranchItem *)(dsti->parent()); + int pi_depth = pi->depth(); + BranchObj *bodst = (BranchObj *)dst; + + if (!tmpParent) { + tmpParent = true; + parObjTmpBuf = parObj; + } + + if (pi_depth < 1) + off = 0; + if (off == 0) + link2ParPos = false; + else + link2ParPos = true; + parObj = bodst; + + setLinkStyle(dst->getDefLinkStyle(dsti)); + + // Move temporary to new position at destination + // Usually the positioning would be done by reposition(), + // but then also the destination branch would "Jump" around... + // Better just do it approximately + if (dsti->depth() == 0) { // new parent is a mapcenter + Vector v = (m - bodst->getChildRefPos()); + v.normalize(); + v.scale(150); + move2RelPos(v.toQPointF()); + } + else { + qreal y; + if (off == 0) { + // Below is needed e.g. in a freshly loaded map, + // bboxTotal seems not to be correct yet + // relinking positions too far below then + calcBBoxSizeWithChildren(); + + // new parent is just a branch, link to it + bodst->calcBBoxSizeWithChildren(); + QRectF t = bodst->getTotalBBox(); + if (dsti->getLastBranch()) + // Move below children of destination + y = t.y() + t.height(); + else + // Move left or right to destination + y = t.y(); + } + else { + if (off < 0) + // we want to link above dst + y = bodst->y() - height() + 12; + else + // we want to link below dst + // Bottom of sel should be 5 pixels above + // the bottom of the branch _below_ the target: + // Don't try to find that branch, guess 12 pixels + y = bodst->getChildRefPos().y() - height() + 12; + } + if (bodst->getOrientation() == LinkableMapObj::LeftOfCenter) + move(bodst->getChildRefPos().x() - linkwidth - bboxTotal.width(), + y); + else + move(bodst->getChildRefPos().x() + linkwidth, y); + } + + // updateLinkGeometry is called implicitly in move + requestReposition(); +} + +void BranchObj::unsetParObjTmp() +{ + if (tmpParent) { + tmpParent = false; + link2ParPos = false; + parObj = parObjTmpBuf; + parObjTmpBuf = NULL; + setLinkStyle(getDefLinkStyle(treeItem->parent())); + updateLinkGeometry(); + } +} + +void BranchObj::setVisibility(bool v, int toDepth) +{ + BranchItem *bi = (BranchItem *)treeItem; + if (bi->depth() <= toDepth) { + frame->setVisibility(v); + heading->setVisibility(v); + systemFlagRowObj->setVisibility(v); + standardFlagRowObj->setVisibility(v); + LinkableMapObj::setVisibility(v); + int i; + for (i = 0; i < treeItem->imageCount(); ++i) + treeItem->getImageObjNum(i)->setVisibility(v); + for (i = 0; i < treeItem->xlinkCount(); ++i) + treeItem->getXLinkObjNum(i)->setVisibility(); + + // Only change children, if I am not scrolled + if (!bi->isScrolled() && (bi->depth() < toDepth)) { + // Now go recursivly through all children + for (i = 0; i < treeItem->branchCount(); ++i) + treeItem->getBranchObjNum(i)->setVisibility(v, toDepth); + } + } +} + +void BranchObj::setVisibility(bool v) { setVisibility(v, MAX_DEPTH); } + +void BranchObj::positionContents() +{ + OrnamentedObj::positionContents(); + updateLinkGeometry(); // required before positioning images + for (int i = 0; i < treeItem->imageCount(); ++i) + treeItem->getImageObjNum(i)->reposition(); +} + +void BranchObj::move(double x, double y) { OrnamentedObj::move(x, y); } + +void BranchObj::move(QPointF p) { move(p.x(), p.y()); } + +void BranchObj::moveBy(double x, double y) +{ + OrnamentedObj::moveBy(x, y); + for (int i = 0; i < treeItem->branchCount(); ++i) + treeItem->getBranchObjNum(i)->moveBy(x, y); + positionBBox(); +} + +void BranchObj::moveBy(QPointF p) { moveBy(p.x(), p.y()); } + +void BranchObj::positionBBox() // FIXME-3 consider dimensions of frame + // (thickness, geometry, padding... +{ + QPointF ap = getAbsPos(); + bbox.moveTopLeft(ap); + positionContents(); // this positions FIOs + + // Update links to other branches + XLinkObj *xlo; + for (int i = 0; i < treeItem->xlinkCount(); ++i) { + xlo = treeItem->getXLinkObjNum(i); + if (xlo) + xlo->updateXLink(); + } +} + +void BranchObj::calcBBoxSize() +{ + QSizeF heading_r = heading->getSize(); + qreal heading_w = (qreal)heading_r.width(); + qreal heading_h = (qreal)heading_r.height(); + QSizeF sysflags_r = systemFlagRowObj->getSize(); + qreal sysflags_h = sysflags_r.height(); + qreal sysflags_w = sysflags_r.width(); + QSizeF stanflags_r = standardFlagRowObj->getSize(); + qreal stanflags_h = stanflags_r.height(); + qreal stanflags_w = stanflags_r.width(); + qreal w; + qreal h; + + // set width to sum of all widths + w = heading_w + sysflags_w + stanflags_w; + + // set height to maximum needed height + h = max(sysflags_h, stanflags_h); + h = max(h, heading_h); + + // Save the dimension of flags and heading + ornamentsBBox.setSize(QSizeF(w, h)); + + // clickBox includes Flags and Heading + clickPoly = QPolygonF(ornamentsBBox); + + // Floatimages + QPointF rp; + + topPad = botPad = leftPad = rightPad = 0; + bool incV = ((BranchItem *)treeItem)->getIncludeImagesVer(); + bool incH = ((BranchItem *)treeItem)->getIncludeImagesHor(); + if (incH || incV) { + FloatImageObj *fio; + for (int i = 0; i < treeItem->imageCount(); ++i) { + fio = treeItem->getImageObjNum(i); + rp = fio->getRelPos(); + if (incV) { + qreal y; + if (rp.y() > 0) { + y = rp.y() + fio->height() / 2 - ornamentsBBox.height() / 2; + botPad = max(botPad, y); + } + else { + y = -rp.y() + fio->height() / 2 - + ornamentsBBox.height() / 2; + topPad = max(topPad, y); + } + } + if (incH) { + qreal x; + if (rp.x() > 0) { + x = rp.x() + fio->width() / 2 - ornamentsBBox.width() / 2; + rightPad = max(rightPad, x); + } + else { + x = -rp.x() + fio->width() / 2 - ornamentsBBox.width() / 2; + leftPad = max(leftPad, x); + } + } + } + h += topPad + botPad; + w += leftPad + rightPad; + } + + // Frame thickness + w += frame->getTotalPadding() * 2; + h += frame->getTotalPadding() * 2; + + // Finally set size + bbox.setSize(QSizeF(w, h)); + // if (debug) qDebug()<<"BO: calcBBox "<getHeading()<<" + // bbox="<getType() == TreeItem::MapCenter) { + // set childRefPos to middle of MapCenterObj + QRectF r = clickPoly.boundingRect(); + childRefPos.setX(r.topLeft().x() + r.width() / 2); + childRefPos.setY(r.topLeft().y() + r.height() / 2); + parPos = childRefPos; + for (int i = 0; i < treeItem->branchCount(); ++i) + treeItem->getBranchObjNum(i)->updateLinkGeometry(); + } + else { + if (orientation == LinkableMapObj::LeftOfCenter) { + // Left of center + if (((BranchItem *)treeItem)->getFrameIncludeChildren()) { + childRefPos = QPointF(ornamentsBBox.bottomLeft().x() - leftPad, + bottomlineY); + parPos = QPointF(bboxTotal.bottomRight().x() - + frame->getPadding() / 2, + bottomlineY); + } + else { + childRefPos = QPointF(ornamentsBBox.bottomLeft().x() - + frame->getPadding(), + bottomlineY); + parPos = QPointF(ornamentsBBox.bottomRight().x(), bottomlineY); + } + } + else { + // Right of center + if (((BranchItem *)treeItem)->getFrameIncludeChildren()) { + childRefPos = QPointF( + ornamentsBBox.bottomRight().x() + rightPad, bottomlineY); + parPos = QPointF(bboxTotal.bottomLeft().x() + + frame->getPadding() / 2, + bottomlineY); + } + else { + childRefPos = QPointF(ornamentsBBox.bottomRight().x() + + frame->getPadding(), + bottomlineY); + parPos = QPointF(ornamentsBBox.bottomLeft().x(), bottomlineY); + } + } + } +} + +void BranchObj::updateVisuals() +{ + if (!treeItem) { + qWarning("BranchObj::udpateHeading treeItem==NULL"); + return; + } + QString s = treeItem->getHeadingText(); + if (s != heading->text()) + heading->setText(s); + + // Update standard flags active in TreeItem + QList TIactiveFlagUids = treeItem->activeFlagUids(); + standardFlagRowObj->updateActiveFlagObjs( + TIactiveFlagUids, standardFlagsMaster, userFlagsMaster); + + // Add missing system flags active in TreeItem + TIactiveFlagUids = treeItem->activeSystemFlagUids(); + systemFlagRowObj->updateActiveFlagObjs(TIactiveFlagUids, systemFlagsMaster); + + calcBBoxSize(); +} + +void BranchObj::setDefAttr(BranchModification mod, bool keepFrame) +{ + + // Note: not needed in 3.x.0 versions, + // where MapDesign will be used + QFont font = treeItem->getModel()->getMapDefaultFont(); + qreal fontsize = font.pointSizeF(); + switch (treeItem->depth()) { + case 0: + break; + case 1: + fontsize = fontsize - 2; + break; + case 2: + fontsize = fontsize - 4; + break; + default: + fontsize = fontsize - 6; + break; + } + setLinkStyle(getDefLinkStyle(treeItem->parent())); + setLinkColor(); + font.setPointSizeF(fontsize); + heading->setFont(font); + + if (mod == NewBranch && !keepFrame) { + if (treeItem->depth() == 0) { + setFrameType(FrameObj::RoundedRectangle); + setFrameBorderWidth(2); + if (usingDarkTheme) { + setFramePenColor(QColor(Qt::white)); + setFrameBrushColor(QColor(85, 85, 127)); + treeItem->setHeadingColor(QColor(Qt::white)); + } else { + setFramePenColor(QColor(Qt::black)); + setFrameBrushColor(QColor(Qt::white)); + } + } else + setFrameType(FrameObj::NoFrame); + } + if (mod == NewBranch) + setColor(treeItem->getHeadingColor()); + else { + // Relinked mapcenters + if (!keepFrame && getFrameType() != FrameObj::NoFrame) + setFrameType(FrameObj::NoFrame); + + // Also set styles for children + for (int i = 0; i < treeItem->branchCount(); ++i) + treeItem->getBranchObjNum(i)->setDefAttr(MovedBranch, keepFrame); + } + calcBBoxSize(); +} + +void BranchObj::alignRelativeTo(QPointF ref, bool alignSelf) +{ + // Define some heights + qreal th = bboxTotal.height(); + qreal ch = 0; // Sum of childrens heights + for (int i = 0; i < treeItem->branchCount(); ++i) + ch += treeItem->getBranchObjNum(i)->getTotalBBox().height(); + + int depth = 0; + BranchItem::LayoutHint layoutHint = BranchItem::AutoPositioning; + if (parObj) { + TreeItem *pi = parObj->getTreeItem(); + depth = 1 + pi->depth(); + layoutHint = + ((BranchItem *)treeItem)->parentBranch()->getChildrenLayout(); + } + + // set useRelPos, depending on layout + if (depth > 1) { + if (layoutHint == BranchItem::FreePositioning) { + if (!useRelPos) { + useRelPos = true; + // if we used relPos before, set known positions + // "known" means any position != (0,0) + if (relPos == QPointF(0, 0)) + // use current position to get relPos() + setRelPos(); + } + } + else + useRelPos = false; + } + + // TODO testing + /* + if (debug) + { + QString o; + switch (orientation) + { + case UndefinedOrientation: o = "UndefOrientation"; break; + case LeftOfCenter: o = "LeftOfCenter"; break; + case RightOfCenter: o = "RightOfCenter"; break; + } + + QString h=QString (depth+1,' '); + h += treeItem->getHeadingPlain(); + h += QString (25,' '); + h.truncate (25); + QPointF pp; + if (parObj) pp = parObj->getChildRefPos(); + qDebug() << "BO::alignRelTo for "<