/* TikZiT - a GUI diagram editor for TikZ Copyright (C) 2018 Aleks Kissinger This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "tikzit.h" #include "edgeitem.h" #include #include EdgeItem::EdgeItem(Edge *edge) { _edge = edge; setFlag(QGraphicsItem::ItemIsSelectable); _cp1Item = new QGraphicsEllipseItem(this); _cp1Item->setParentItem(this); _cp1Item->setRect(GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * 0.2, GLOBAL_SCALEF * 0.2); _cp1Item->setVisible(false); _cp2Item = new QGraphicsEllipseItem(this); _cp2Item->setParentItem(this); _cp2Item->setRect(GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * (-0.1), GLOBAL_SCALEF * 0.2, GLOBAL_SCALEF * 0.2); _cp2Item->setVisible(false); readPos(); } void EdgeItem::readPos() { //_edge->setAttributesFromData(); _edge->updateControls(); QPainterPath path; path.moveTo (toScreen(_edge->tail())); if (_edge->bend() != 0 || !_edge->basicBendMode()) { path.cubicTo(toScreen(_edge->cp1()), toScreen(_edge->cp2()), toScreen(_edge->head())); } else { path.lineTo(toScreen(_edge->head())); } setPath(path); _cp1Item->setPos(toScreen(_edge->cp1())); _cp2Item->setPos(toScreen(_edge->cp2())); } void EdgeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { //QGraphicsPathItem::paint(painter, option, widget); QPen pen = _edge->style()->pen(); painter->setPen(pen); painter->setBrush(Qt::NoBrush); painter->drawPath(path()); QPointF ht = _edge->headTangent(); QPointF hLeft(-ht.y(), ht.x()); QPointF hRight(ht.y(), -ht.x()); QPointF tt = _edge->tailTangent(); QPointF tLeft(-ht.y(), ht.x()); QPointF tRight(ht.y(), -ht.x()); pen.setStyle(Qt::SolidLine); painter->setPen(pen); switch (_edge->style()->arrowHead()) { case Style::Flat: { painter->drawLine( toScreen(_edge->head() + hLeft), toScreen(_edge->head() + hRight)); break; } case Style::Pointer: { QPainterPath pth; pth.moveTo(toScreen(_edge->head() + ht + hLeft)); pth.lineTo(toScreen(_edge->head())); pth.lineTo(toScreen(_edge->head() + ht + hRight)); painter->drawPath(pth); break; } case Style::NoTip: break; } //QPen outline = QPen(Qt::red); //painter->setPen(outline); //painter->drawPath(_expPath); //painter->setPen(pen); switch (_edge->style()->arrowTail()) { case Style::Flat: { painter->drawLine( toScreen(_edge->tail() + tLeft), toScreen(_edge->tail() + tRight)); break; } case Style::Pointer: { QPainterPath pth; pth.moveTo(toScreen(_edge->tail() + tt + tLeft)); pth.lineTo(toScreen(_edge->tail())); pth.lineTo(toScreen(_edge->tail() + tt + tRight)); painter->drawPath(pth); break; } case Style::NoTip: break; } if (isSelected()) { QColor draw; QColor draw1; QColor fill; if (_edge->basicBendMode()) { draw = Qt::blue; draw1 = QColor(100,100,255,100); fill = QColor(200,200,255,50); } else { draw = Qt::darkGreen; draw1 = QColor(0, 150, 0, 50); fill = QColor(200,255,200,150); } painter->setPen(QPen(draw1)); qreal r = GLOBAL_SCALEF * _edge->cpDist(); painter->drawEllipse(toScreen(_edge->source()->point()), r, r); painter->drawEllipse(toScreen(_edge->target()->point()), r, r); painter->setPen(QPen(draw)); painter->setBrush(QBrush(fill)); painter->drawLine(toScreen(_edge->tail()), toScreen(_edge->cp1())); painter->drawLine(toScreen(_edge->head()), toScreen(_edge->cp2())); if (scene()) { TikzScene *sc = static_cast(scene()); painter->setFont(Tikzit::LABEL_FONT); QFontMetrics fm(Tikzit::LABEL_FONT); QRectF rect = fm.boundingRect("<>"); if (sc->highlightHeads()) { QPointF headMark(_edge->target()->point().x(), _edge->target()->point().y() + _edge->cpDist() - 0.25); rect.moveCenter(toScreen(headMark)); painter->drawText(rect, Qt::AlignCenter, "<>"); } else if (sc->highlightTails()) { QPointF tailMark(_edge->source()->point().x(), _edge->source()->point().y() + _edge->cpDist() - 0.25); rect.moveCenter(toScreen(tailMark)); painter->drawText(rect, Qt::AlignCenter, "<>"); } } //painter->drawEllipse(toScreen(_edge->cp1()), r, r); //painter->drawEllipse(toScreen(_edge->cp2()), r, r); _cp1Item->setPen(QPen(draw)); _cp1Item->setBrush(QBrush(fill)); _cp1Item->setVisible(true); _cp2Item->setPen(QPen(draw)); _cp2Item->setBrush(QBrush(fill)); _cp2Item->setVisible(true); r = GLOBAL_SCALEF * 0.05; painter->setPen(QPen(Qt::black)); painter->setBrush(QBrush(QColor(255,255,255,200))); painter->drawEllipse(toScreen(_edge->mid()), r, r); } else { _cp1Item->setVisible(false); _cp2Item->setVisible(false); } } QRectF EdgeItem::boundingRect() const { return _boundingRect; } QPainterPath EdgeItem::shape() const { return _expPath; } Edge *EdgeItem::edge() const { return _edge; } QGraphicsEllipseItem *EdgeItem::cp1Item() const { return _cp1Item; } QGraphicsEllipseItem *EdgeItem::cp2Item() const { return _cp2Item; } QPainterPath EdgeItem::path() const { return _path; } void EdgeItem::setPath(const QPainterPath &path) { prepareGeometryChange(); _path = path; // get the shape of the edge, and expand a bit to make selection easier QPainterPathStroker stroker; stroker.setWidth(8); stroker.setJoinStyle(Qt::MiterJoin); _expPath = stroker.createStroke(_path).simplified(); float r = GLOBAL_SCALEF * (_edge->cpDist() + 0.2); _boundingRect = _path.boundingRect().adjusted(-r,-r,r,r); update(); }