package Arrow; use strict; use warnings; use QtCore4; use QtGui4; # [0] use QtCore4::isa qw( Qt::GraphicsLineItem ); use Math::Trig; use constant Type => Qt::GraphicsLineItem::UserType() + 4; sub type() { return Type; } sub setColor { this->{myColor} = shift; } sub startItem() { return this->{myStartItem}; } sub endItem() { return this->{myEndItem}; } use QtCore4::slots updatePosition => []; sub myColor() { return this->{myColor}; } sub arrowHead() { return this->{arrowHead}; } my $Pi = 3.14; # [0] sub NEW { my ($class, $startItem, $endItem, $parent, $scene) = @_; $class->SUPER::NEW($parent, $scene); this->{myStartItem} = $startItem; this->{myEndItem} = $endItem; this->setFlag(Qt::GraphicsItem::ItemIsSelectable(), 1); this->{myColor} = Qt::black(); this->setPen(Qt::Pen(Qt::Brush(this->myColor), 2, Qt::SolidLine(), Qt::RoundCap(), Qt::RoundJoin())); this->{arrowHead} = Qt::PolygonF(); } # [0] # [1] sub boundingRect { my $extra = (this->pen()->width() + 20) / 2.0; return Qt::RectF(this->line()->p1(), Qt::SizeF(this->line()->p2()->x() - this->line()->p1()->x(), this->line()->p2()->y() - this->line()->p1()->y())) ->normalized() ->adjusted(-$extra, -$extra, $extra, $extra); } # [1] # [2] sub shape { my $path = Qt::GraphicsLineItem::shape(); $path->addPolygon(this->arrowHead); return $path; } # [2] # [3] sub updatePosition { my $line = Qt::LineF(this->mapFromItem(this->startItem, 0, 0), this->mapFromItem(this->endItem, 0, 0)); this->setLine($line); } # [3] # [4] sub paint { my ($painter) = @_; if (this->startItem->collidesWithItem(this->endItem)) { return; } my $myPen = this->pen(); $myPen->setColor(Qt::Color(this->myColor)); my $arrowSize = 20; $painter->setPen($myPen); $painter->setBrush(Qt::Brush(this->myColor)); # [4] //! [5] my $centerLine = Qt::LineF(this->startItem->pos(), this->endItem->pos()); my $endPolygon = Qt::PolygonF(this->endItem->polygon()); my $p1 = $endPolygon->[0] + this->endItem->pos(); my $p2; my $intersectPoint = Qt::PointF(); my $polyLine; for (my $i = 1; $i < scalar @{$endPolygon}; ++$i) { $p2 = $endPolygon->[$i] + this->endItem->pos(); $polyLine = Qt::LineF($p1, $p2); my $intersectType = $polyLine->intersect($centerLine, $intersectPoint); if ($intersectType == Qt::LineF::BoundedIntersection()) { last; } $p1 = $p2; } this->setLine(Qt::LineF($intersectPoint, this->startItem->pos())); # [5] //! [6] my $angle = acos(this->line()->dx() / this->line()->length()); if (this->line()->dy() >= 0) { $angle = ($Pi * 2) - $angle; } my $arrowP1 = this->line()->p1() + Qt::PointF(sin($angle + $Pi / 3) * $arrowSize, cos($angle + $Pi / 3) * $arrowSize); my $arrowP2 = this->line()->p1() + Qt::PointF(sin($angle + $Pi - $Pi / 3) * $arrowSize, cos($angle + $Pi - $Pi / 3) * $arrowSize); this->{arrowHead} = Qt::PolygonF( [ this->line->p1(), $arrowP1, $arrowP2 ] ); # [6] //! [7] $painter->drawLine(this->line()); $painter->drawPolygon(Qt::PolygonF(this->arrowHead)); if (this->isSelected()) { $painter->setPen(Qt::Pen(Qt::Brush(this->myColor), 1, Qt::DashLine())); my $myLine = this->line(); $myLine->translate(0, 4.0); $painter->drawLine($myLine); $myLine->translate(0,-8.0); $painter->drawLine($myLine); } } # [7] 1;