Files
qad/libs/blockview/blockitempin.cpp
2023-04-13 18:21:21 +03:00

249 lines
5.8 KiB
C++

#include "blockview.h"
#include <QApplication>
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<BlockItem *>(parentItem()) == 0) return;
QPen p = qgraphicsitem_cast<BlockItem *>(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<BlockView *>(v)->getPinMC(&m_pin_mc);
QMetaObject::invokeMethod(
v,
[this, v]() { qobject_cast<BlockView *>(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<BlockView *>(v)->pinHoverInOut(nullptr);
}
}