#include "blockview.h" #include BlockItemPin::BlockItemPin(Qt::Alignment a, int bus_type_, const QString & text_, QGraphicsObject * _parent) : QGraphicsObject(_parent) , ell_item(this) , text_item(this) { parent_ = 0; setData(bvidType, bvitPin); setAcceptHoverEvents(true); text_item.setData(bvidMoveParent, true); ell_item.setData(bvidVisualizeSelection, true); br[Disconnected] = QBrush(Qt::lightGray); br[Connected] = QBrush(Qt::darkGreen); br[Hover] = QBrush(Qt::blue); br[Drop] = QBrush(Qt::green); br[Accept] = QBrush(Qt::green); br[Reject] = QBrush(Qt::red); anim_pin_size.setTargetObject(this); anim_pin_size.setPropertyName("pinSize"); anim_pin_size.setEasingCurve(QEasingCurve::OutElastic); anim_pin_size.setDuration(700); anim_accept.setTargetObject(this); anim_accept.setPropertyName("pinSize"); anim_accept.setEasingCurve(QEasingCurve::InOutQuad); anim_accept.setDuration(150); connect(&anim_accept, SIGNAL(finished()), this, SLOT(animationAccept())); setState(Disconnected); setAlignment(a); setBusType(bus_type_); setText(text_); setZValue(2.); _reparent(); } void BlockItemPin::setPen(const QPen & p) { ell_item.setPen(p); } QPen BlockItemPin::pen() const { return ell_item.pen(); } void BlockItemPin::setBrush(const QBrush & b) { ell_item.setBrush(b); } QBrush BlockItemPin::brush() const { return ell_item.brush(); } QString BlockItemPin::text() const { return text_item.text(); } void BlockItemPin::setBusType(int type_) { bus_type = type_; } void BlockItemPin::setAlignment(Qt::Alignment a) { align = a; _init(true); } void BlockItemPin::setText(const QString & t) { text_item.setText(t); _init(true); } void BlockItemPin::animAccept() { if (!((BlockView *)scene()->views().back())->isBlockAnimationEnabled() && anim_accept.state() != QAbstractAnimation::Running) return; anim_accept.setStartValue(pinSize()); anim_accept.setEndValue(10.); anim_accept.start(); } QRectF BlockItemPin::boundingRect() const { return ell_item.boundingRect().translated(ell_item.pos()) | text_item.boundingRect().translated(text_item.pos()); } void BlockItemPin::setState(State s) { State os = state_; state_ = s; setBrush(br[int(state_)]); if (s == Accept && os != Accept) { animAccept(); } update(); } void BlockItemPin::saveState() { sstate_.push(state_); } bool BlockItemPin::restoreState() { if (sstate_.isEmpty()) return false; setState(sstate_.pop()); return true; } void BlockItemPin::clearStateStack() { sstate_.clear(); } void BlockItemPin::enlargePin(bool enlarge) { double sz = enlarge ? 12. : 7; if (anim_accept.state() == QAbstractAnimation::Running && enlarge) { anim_accept.stop(); resizePin(sz); } if (!((BlockView *)scene()->views().back())->isBlockAnimationEnabled()) { resizePin(sz); return; } if (sz == anim_pin_size.endValue()) return; anim_pin_size.stop(); anim_pin_size.setStartValue(pinSize()); anim_pin_size.setEndValue(sz); anim_pin_size.start(); } void BlockItemPin::resizePin(double r) { ell_item.setRect(-r, -r, r + r, r + r); } double BlockItemPin::pinSize() const { return ell_item.rect().width() / 2.; } void BlockItemPin::animationAccept() { if (anim_accept.endValue().toDouble() == 7.) return; anim_accept.setStartValue(pinSize()); anim_accept.setEndValue(7.); anim_accept.start(); } void BlockItemPin::_init(bool affect_parent) { text_item.setFont(AlignedTextItem::sceneFont(QApplication::font())); QRectF tbr = text_item.boundingRect(); const double r = 7.; ell_item.setRect(-r, -r, r + r, r + r); ell_item.setSpanAngle(16 * 180); text_item.resetTransform(); text_item.setPos(0, -tbr.height() / 2.); text_item.setTransformOriginPoint(0, tbr.height() / 2.); switch (align) { case Qt::AlignBottom: ell_item.setStartAngle(16 * 0); text_item.setRotation(-90.); text_item.moveBy(0, -r * 1.5); break; case Qt::AlignRight: ell_item.setStartAngle(16 * 90); text_item.setRotation(0.); text_item.moveBy(-tbr.width() - r * 1.5, 0); break; case Qt::AlignTop: ell_item.setStartAngle(16 * 180); text_item.setRotation(-90.); text_item.moveBy(0, tbr.width() + r * 1.5); break; case Qt::AlignLeft: ell_item.setStartAngle(16 * 270); text_item.setRotation(0.); text_item.moveBy(r * 1.5, 0); break; default: break; } if (affect_parent && parent_) parent_->arrangePins(); } void BlockItemPin::_reparent() { if (parentItem() == 0) return; if (qgraphicsitem_cast(parentItem()) == 0) return; QPen p = qgraphicsitem_cast(parentItem())->g_main.pen(); ell_item.setPen(p); if (scene()) { text_item.setFont(AlignedTextItem::sceneFont(scene()->font())); QRectF tbr = text_item.boundingRect(); text_item.resetTransform(); text_item.setPos(0, -tbr.height() / 2.); text_item.setTransformOriginPoint(0, tbr.height() / 2.); } } QGraphicsView * BlockItemPin::_view() const { if (!scene()) return 0; if (scene()->views().isEmpty()) return 0; return scene()->views().back(); } QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) { if (change == QGraphicsItem::ItemParentChange) _reparent(); return QGraphicsItem::itemChange(change, value); } void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) { QGraphicsView * v = _view(); bool m_pin_mc = false; if (v) { qobject_cast(v)->getPinMC(&m_pin_mc); QMetaObject::invokeMethod( v, [this, v]() { qobject_cast(v)->pinHoverInOut(this); }, Qt::QueuedConnection); } if ((state() != Disconnected) && !m_pin_mc) return; saveState(); setState(BlockItemPin::Hover); enlargePin(true); update(); } void BlockItemPin::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) { QGraphicsView * v = _view(); restoreState(); enlargePin(false); update(); if (v) { qobject_cast(v)->pinHoverInOut(nullptr); } }