|
|
|
/*
|
|
|
|
* Copyright (C) 2013 Open Education Foundation
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour
|
|
|
|
* l'Education Numérique en Afrique (GIP ENA)
|
|
|
|
*
|
|
|
|
* This file is part of OpenBoard.
|
|
|
|
*
|
|
|
|
* OpenBoard 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, version 3 of the License,
|
|
|
|
* with a specific linking exception for the OpenSSL project's
|
|
|
|
* "OpenSSL" library (or with modified versions of it that use the
|
|
|
|
* same license as the "OpenSSL" library).
|
|
|
|
*
|
|
|
|
* OpenBoard 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 OpenBoard. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <QGraphicsPolygonItem>
|
|
|
|
#include <QPolygonF>
|
|
|
|
|
|
|
|
#include "tools/UBGraphicsTriangle.h"
|
|
|
|
#include "core/UBApplication.h"
|
|
|
|
#include "board/UBBoardController.h"
|
|
|
|
#include "board/UBDrawingController.h"
|
|
|
|
#include "domain/UBGraphicsScene.h"
|
|
|
|
|
|
|
|
#include "core/memcheck.h"
|
|
|
|
|
|
|
|
const QRect UBGraphicsTriangle::sDefaultRect = QRect(0, 0, 800, 400);
|
|
|
|
const UBGraphicsTriangle::UBGraphicsTriangleOrientation UBGraphicsTriangle::sDefaultOrientation =
|
|
|
|
UBGraphicsTriangle::BottomLeft;
|
|
|
|
|
|
|
|
UBGraphicsTriangle::UBGraphicsTriangle()
|
|
|
|
: UBAbstractDrawRuler()
|
|
|
|
, QGraphicsPolygonItem()
|
|
|
|
, angle(0)
|
|
|
|
, mResizing1(false)
|
|
|
|
, mResizing2(false)
|
|
|
|
, mRotating(false)
|
|
|
|
|
|
|
|
{
|
|
|
|
setRect(sDefaultRect, sDefaultOrientation);
|
|
|
|
|
|
|
|
create(*this);
|
|
|
|
|
|
|
|
mHFlipSvgItem = new QGraphicsSvgItem(":/images/hflipTool.svg", this);
|
|
|
|
mHFlipSvgItem->setVisible(false);
|
|
|
|
|
|
|
|
mHFlipSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control));
|
|
|
|
|
|
|
|
mVFlipSvgItem = new QGraphicsSvgItem(":/images/vflipTool.svg", this);
|
|
|
|
mVFlipSvgItem->setVisible(false);
|
|
|
|
mVFlipSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control));
|
|
|
|
|
|
|
|
mRotateSvgItem = new QGraphicsSvgItem(":/images/rotateTool.svg", this);
|
|
|
|
mRotateSvgItem->setVisible(false);
|
|
|
|
mRotateSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control));
|
|
|
|
|
|
|
|
setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::CppTool)); //Necessary to set if we want z value to be assigned correctly
|
|
|
|
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
|
|
|
|
|
|
|
updateResizeCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::updateResizeCursor()
|
|
|
|
{
|
|
|
|
QPixmap pix(":/images/cursors/resize.png");
|
|
|
|
QTransform itemTransform = sceneTransform();
|
|
|
|
QRectF itemRect = boundingRect();
|
|
|
|
|
|
|
|
QPointF topLeft = itemTransform.map(itemRect.topLeft());
|
|
|
|
QPointF topRight = itemTransform.map(itemRect.topRight());
|
|
|
|
QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft());
|
|
|
|
|
|
|
|
QLineF topLine(topLeft, topRight);
|
|
|
|
QLineF leftLine(topLeft, bottomLeft);
|
|
|
|
|
|
|
|
qreal angle = topLine.angle();
|
|
|
|
QTransform tr1;
|
|
|
|
tr1.rotate(- angle);
|
|
|
|
mResizeCursor1 = QCursor(pix.transformed(tr1, Qt::SmoothTransformation), pix.width() / 2, pix.height() / 2);
|
|
|
|
|
|
|
|
angle = leftLine.angle();
|
|
|
|
QTransform tr2;
|
|
|
|
tr2.rotate(- angle);
|
|
|
|
mResizeCursor2 = QCursor(pix.transformed(tr2, Qt::SmoothTransformation), pix.width() / 2, pix.height() / 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UBGraphicsTriangle::~UBGraphicsTriangle()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
UBItem* UBGraphicsTriangle::deepCopy(void) const
|
|
|
|
{
|
|
|
|
UBGraphicsTriangle* copy = new UBGraphicsTriangle();
|
|
|
|
|
|
|
|
copyItemParameters(copy);
|
|
|
|
|
|
|
|
// TODO UB 4.7 ... complete all members ?
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::copyItemParameters(UBItem *copy) const
|
|
|
|
{
|
|
|
|
UBGraphicsTriangle* cp = dynamic_cast<UBGraphicsTriangle*>(copy);
|
|
|
|
if (cp)
|
|
|
|
{
|
|
|
|
cp->setPos(this->pos());
|
|
|
|
cp->setPolygon(this->polygon());
|
|
|
|
cp->setTransform(this->transform());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::setRect(qreal x, qreal y, qreal w, qreal h, UBGraphicsTriangleOrientation orientation)
|
|
|
|
{
|
|
|
|
QPolygonF polygon;
|
|
|
|
polygon << QPointF(x, y) << QPoint(x, y + h) << QPoint(x+w, y + h);
|
|
|
|
setPolygon(polygon);
|
|
|
|
|
|
|
|
setOrientation(orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::setOrientation(UBGraphicsTriangleOrientation orientation)
|
|
|
|
{
|
|
|
|
mOrientation = orientation;
|
|
|
|
calculatePoints(boundingRect());
|
|
|
|
|
|
|
|
QPolygonF polygon;
|
|
|
|
polygon << A1 << B1 << C1;
|
|
|
|
setPolygon(polygon);
|
|
|
|
}
|
|
|
|
|
|
|
|
UBGraphicsScene* UBGraphicsTriangle::scene() const
|
|
|
|
{
|
|
|
|
return static_cast<UBGraphicsScene*>(QGraphicsPolygonItem::scene());
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::calculatePoints(const QRectF& r)
|
|
|
|
{
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
|
|
|
|
case BottomLeft:
|
|
|
|
A1.setX(r.left()); A1.setY(r.top());
|
|
|
|
B1.setX(r.left()); B1.setY(r.bottom());
|
|
|
|
C1.setX(r.right()); C1.setY(r.bottom());
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
A1.setX(r.left()); A1.setY(r.bottom());
|
|
|
|
B1.setX(r.left()); B1.setY(r.top());
|
|
|
|
C1.setX(r.right()); C1.setY(r.top());
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
A1.setX(r.right()); A1.setY(r.bottom());
|
|
|
|
B1.setX(r.right()); B1.setY(r.top());
|
|
|
|
C1.setX(r.left()); C1.setY(r.top());
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
A1.setX(r.right()); A1.setY(r.top());
|
|
|
|
B1.setX(r.right()); B1.setY(r.bottom());
|
|
|
|
C1.setX(r.left()); C1.setY(r.bottom());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
C = sqrt(rect().width() * rect().width() + rect().height() * rect().height());
|
|
|
|
qreal L = (C * d + rect().width() * d)/ rect().height();
|
|
|
|
qreal K = (C * d + rect().height() * d)/ rect().width();
|
|
|
|
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
A2.setX(r.left() + d); A2.setY(r.top() + K);
|
|
|
|
B2.setX(r.left() + d); B2.setY(r.bottom() - d);
|
|
|
|
C2.setX(r.right() - L); C2.setY(r.bottom() - d);
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
A2.setX(r.left() + d); A2.setY(r.bottom() - K);
|
|
|
|
B2.setX(r.left() + d); B2.setY(r.top() + d);
|
|
|
|
C2.setX(r.right() - L); C2.setY(r.top() + d);
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
A2.setX(r.right() - d); A2.setY(r.bottom() - K);
|
|
|
|
B2.setX(r.right() - d); B2.setY(r.top() + d);
|
|
|
|
C2.setX(r.left() + L); C2.setY(r.top() + d);
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
A2.setX(r.right() - d); A2.setY(r.top() + K);
|
|
|
|
B2.setX(r.right() - d); B2.setY(r.bottom() - d);
|
|
|
|
C2.setX(r.left() + L); C2.setY(r.bottom() - d);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
W1 = rect().height() * d / C;
|
|
|
|
H1 = rect().width() * d / C;
|
|
|
|
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
CC.setX(r.right() - L + W1); CC.setY(r.bottom() - d - H1);
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
CC.setX(r.right() - L + W1); CC.setY(r.top() + d + H1);
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
CC.setX(r.left() + L - W1); CC.setY(r.top() + d + H1);
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
CC.setX(r.left() + L - W1); CC.setY(r.top() - d - H1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
|
|
|
|
{
|
|
|
|
|
|
|
|
painter->setPen(Qt::NoPen);
|
|
|
|
|
|
|
|
QPolygonF polygon;
|
|
|
|
|
|
|
|
QLinearGradient gradient1(QPointF(A1.x(), 0), QPointF(A2.x(), 0));
|
|
|
|
gradient1.setColorAt(0, edgeFillColor());
|
|
|
|
gradient1.setColorAt(1, middleFillColor());
|
|
|
|
painter->setBrush(gradient1);
|
|
|
|
polygon << A1 << A2 << B2 << B1;
|
|
|
|
painter->drawPolygon(polygon);
|
|
|
|
polygon.clear();
|
|
|
|
|
|
|
|
QLinearGradient gradient2(QPointF(0, B1.y()), QPointF(0, B2.y()));
|
|
|
|
gradient2.setColorAt(0, edgeFillColor());
|
|
|
|
gradient2.setColorAt(1, middleFillColor());
|
|
|
|
painter->setBrush(gradient2);
|
|
|
|
polygon << B1 << B2 << C2 << C1;
|
|
|
|
painter->drawPolygon(polygon);
|
|
|
|
polygon.clear();
|
|
|
|
|
|
|
|
QLinearGradient gradient3(CC, C2);
|
|
|
|
gradient3.setColorAt(0, edgeFillColor());
|
|
|
|
gradient3.setColorAt(1, middleFillColor());
|
|
|
|
painter->setBrush(gradient3);
|
|
|
|
polygon << C1 << C2 << A2 << A1;
|
|
|
|
painter->drawPolygon(polygon);
|
|
|
|
polygon.clear();
|
|
|
|
|
|
|
|
|
|
|
|
painter->setBrush(Qt::NoBrush);
|
|
|
|
painter->setPen(drawColor());
|
|
|
|
|
|
|
|
polygon << A1 << B1 << C1;
|
|
|
|
painter->drawPolygon(polygon);
|
|
|
|
polygon.clear();
|
|
|
|
|
|
|
|
polygon << A2 << B2 << C2;
|
|
|
|
painter->drawPolygon(polygon);
|
|
|
|
|
|
|
|
paintGraduations(painter);
|
|
|
|
|
|
|
|
mAntiScaleRatio = 1 / (UBApplication::boardController->systemScaleFactor() * UBApplication::boardController->currentZoom());
|
|
|
|
QTransform antiScaleTransform;
|
|
|
|
antiScaleTransform.scale(mAntiScaleRatio, mAntiScaleRatio);
|
|
|
|
|
|
|
|
mCloseSvgItem->setTransform(antiScaleTransform);
|
|
|
|
mHFlipSvgItem->setTransform(antiScaleTransform);
|
|
|
|
mVFlipSvgItem->setTransform(antiScaleTransform);
|
|
|
|
mRotateSvgItem->setTransform(antiScaleTransform);
|
|
|
|
|
|
|
|
mCloseSvgItem->setPos(closeButtonRect().topLeft());
|
|
|
|
mHFlipSvgItem->setPos(hFlipRect().topLeft());
|
|
|
|
mVFlipSvgItem->setPos(vFlipRect().topLeft());
|
|
|
|
mRotateSvgItem->setPos(rotateRect().topLeft());
|
|
|
|
|
|
|
|
if (mShowButtons || mResizing1 || mResizing2)
|
|
|
|
{
|
|
|
|
painter->setBrush(QColor(0, 0, 0));
|
|
|
|
if (mShowButtons || mResizing1)
|
|
|
|
painter->drawPolygon(resize1Polygon());
|
|
|
|
if (mShowButtons || mResizing2)
|
|
|
|
painter->drawPolygon(resize2Polygon());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QPainterPath UBGraphicsTriangle::shape() const
|
|
|
|
{
|
|
|
|
QPainterPath tShape;
|
|
|
|
QPolygonF tPolygon;
|
|
|
|
|
|
|
|
tPolygon << A1 << B1 << C1;
|
|
|
|
tShape.addPolygon(tPolygon);
|
|
|
|
tPolygon.clear();
|
|
|
|
|
|
|
|
tPolygon << A2 << B2 << C2;
|
|
|
|
tShape.addPolygon(tPolygon);
|
|
|
|
tPolygon.clear();
|
|
|
|
|
|
|
|
return tShape;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::paintGraduations(QPainter *painter)
|
|
|
|
{
|
|
|
|
qreal kx = (mOrientation == TopLeft || mOrientation == BottomLeft) ? 1 : -1;
|
|
|
|
qreal ky = (mOrientation == BottomLeft || mOrientation == BottomRight) ? 1 : -1;
|
|
|
|
|
|
|
|
painter->save();
|
|
|
|
painter->setFont(font());
|
|
|
|
QFontMetricsF fontMetrics(painter->font());
|
|
|
|
for (int millimeters = 0; millimeters < (rect().width() - sLeftEdgeMargin - sRoundingRadius) / sPixelsPerMillimeter; millimeters++)
|
|
|
|
{
|
|
|
|
int graduationX = rotationCenter().x() + kx * sPixelsPerMillimeter * millimeters;
|
|
|
|
int graduationHeight = (0 == millimeters % UBGeometryUtils::millimetersPerCentimeter) ?
|
|
|
|
UBGeometryUtils::centimeterGraduationHeight :
|
|
|
|
((0 == millimeters % UBGeometryUtils::millimetersPerHalfCentimeter) ?
|
|
|
|
UBGeometryUtils::halfCentimeterGraduationHeight : UBGeometryUtils::millimeterGraduationHeight);
|
|
|
|
|
|
|
|
// Check that grad. line inside triangle
|
|
|
|
qreal dx = (kx > 0) ? rect().width() - graduationX : graduationX - rect().x();
|
|
|
|
qreal lineY = rotationCenter().y() - ky * rect().height()/rect().width() * dx;
|
|
|
|
if (mOrientation == BottomLeft || mOrientation == BottomRight)
|
|
|
|
{
|
|
|
|
if (lineY >= rotationCenter().y() - ky * graduationHeight)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (lineY <= rotationCenter().y() - ky * graduationHeight)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
painter->drawLine(QLine(graduationX, rotationCenter().y(), graduationX, rotationCenter().y() - ky * graduationHeight));
|
|
|
|
if (0 == millimeters % UBGeometryUtils::millimetersPerCentimeter)
|
|
|
|
{
|
|
|
|
QString text = QString("%1").arg((int)(millimeters / UBGeometryUtils::millimetersPerCentimeter));
|
|
|
|
int textXRight = graduationX + fontMetrics.width(text) / 2;
|
|
|
|
qreal textWidth = fontMetrics.width(text);
|
|
|
|
qreal textHeight = fontMetrics.tightBoundingRect(text).height() + 5;
|
|
|
|
|
|
|
|
int textY = (ky > 0) ? rotationCenter().y() - 5 - UBGeometryUtils::centimeterGraduationHeight - textHeight
|
|
|
|
: rotationCenter().y() + 5 + UBGeometryUtils::centimeterGraduationHeight;
|
|
|
|
|
|
|
|
bool bText = false;
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
dx = rect().width() - textXRight;
|
|
|
|
lineY = rotationCenter().y() - rect().height()/rect().width() * dx;
|
|
|
|
bText = lineY <= textY;
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
dx = rect().width() - textXRight;
|
|
|
|
lineY = rotationCenter().y() + rect().height()/rect().width() * dx;
|
|
|
|
bText = lineY >= textY + textHeight;
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
dx = textXRight - textWidth - rect().left();
|
|
|
|
lineY = rotationCenter().y() + rect().height()/rect().width() * dx;
|
|
|
|
bText = lineY >= textY + textHeight;
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
dx = textXRight - textWidth - rect().left();
|
|
|
|
lineY = rotationCenter().y() - rect().height()/rect().width() * dx;
|
|
|
|
bText = lineY <= textY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bText)
|
|
|
|
painter->drawText(
|
|
|
|
QRectF(graduationX - textWidth / 2,
|
|
|
|
textY, textWidth, textHeight),
|
|
|
|
Qt::AlignVCenter, text);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
painter->restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::rotateAroundCenter(qreal angle)
|
|
|
|
{
|
|
|
|
qreal oldAngle = this->angle;
|
|
|
|
this->angle = angle;
|
|
|
|
QTransform transform;
|
|
|
|
rotateAroundCenter(transform, rotationCenter());
|
|
|
|
setTransform(transform, true);
|
|
|
|
this->angle = oldAngle + angle; // We have to store absolute value for FLIP case
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::rotateAroundCenter(QTransform& transform, QPointF center)
|
|
|
|
{
|
|
|
|
transform.translate(center.x(), center.y());
|
|
|
|
transform.rotate(angle);
|
|
|
|
transform.translate(- center.x(), - center.y());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QPointF UBGraphicsTriangle::rotationCenter() const
|
|
|
|
{
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
case TopLeft:
|
|
|
|
return B1 + QPointF(sLeftEdgeMargin, 0);
|
|
|
|
case TopRight:
|
|
|
|
case BottomRight:
|
|
|
|
return B1 - QPointF(sLeftEdgeMargin, 0);
|
|
|
|
}
|
|
|
|
return QPointF(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF UBGraphicsTriangle::closeButtonRect() const
|
|
|
|
{
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
return QRectF(B2.x() - mCloseSvgItem->boundingRect().width() - 5,
|
|
|
|
B2.y() - mCloseSvgItem->boundingRect().height() - 5,
|
|
|
|
mCloseSvgItem->boundingRect().width(),
|
|
|
|
mCloseSvgItem->boundingRect().height());
|
|
|
|
case TopLeft:
|
|
|
|
return QRectF(B2.x() - mCloseSvgItem->boundingRect().width() - 5,
|
|
|
|
B2.y() + 5,
|
|
|
|
mCloseSvgItem->boundingRect().width(),
|
|
|
|
mCloseSvgItem->boundingRect().height());
|
|
|
|
case TopRight:
|
|
|
|
return QRectF(B2.x() + 5,
|
|
|
|
B2.y() + 5,
|
|
|
|
mCloseSvgItem->boundingRect().width(),
|
|
|
|
mCloseSvgItem->boundingRect().height());
|
|
|
|
case BottomRight:
|
|
|
|
return QRectF(B2.x() + 5,
|
|
|
|
B2.y() - mCloseSvgItem->boundingRect().height() - 5,
|
|
|
|
mCloseSvgItem->boundingRect().width(),
|
|
|
|
mCloseSvgItem->boundingRect().height());
|
|
|
|
}
|
|
|
|
return QRectF(0,0,0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
QPolygonF UBGraphicsTriangle::resize1Polygon() const
|
|
|
|
{
|
|
|
|
qreal x1, y1;
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
x1 = -1;
|
|
|
|
y1 = -1;
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
x1 = -1;
|
|
|
|
y1 = 1;
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
x1 = 1;
|
|
|
|
y1 = 1;
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
x1 = 1;
|
|
|
|
y1 = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
QPointF P1(C1.x() + x1 * sArrowLength, C1.y());
|
|
|
|
QPointF P2(C1.x() + x1 * sArrowLength * rect().width()/C, C1.y() + y1 * sArrowLength * rect().height() / C);
|
|
|
|
QPolygonF p;
|
|
|
|
p << C1 << P1 << P2;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
QPolygonF UBGraphicsTriangle::resize2Polygon() const
|
|
|
|
{
|
|
|
|
qreal x1, y1;
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
x1 = 1;
|
|
|
|
y1 = 1;
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
x1 = 1;
|
|
|
|
y1 = -1;
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
x1 = -1;
|
|
|
|
y1 = -1;
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
x1 = -1;
|
|
|
|
y1 = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
QPointF P1(A1.x(), A1.y() + y1 * sArrowLength);
|
|
|
|
QPointF P2(A1.x() + x1 * sArrowLength * rect().width()/C,
|
|
|
|
A1.y() + y1 * sArrowLength * rect().height() / C);
|
|
|
|
QPolygonF p;
|
|
|
|
p << A1 << P1 << P2;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF UBGraphicsTriangle::hFlipRect() const
|
|
|
|
{
|
|
|
|
qreal dy = mVFlipSvgItem->boundingRect().height() + mCloseSvgItem->boundingRect().height() + 10;
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
return QRectF(B2.x() - mHFlipSvgItem->boundingRect().width() - 5,
|
|
|
|
B2.y() - mHFlipSvgItem->boundingRect().height() - 5 - dy,
|
|
|
|
mHFlipSvgItem->boundingRect().width(),
|
|
|
|
mHFlipSvgItem->boundingRect().height());
|
|
|
|
case TopLeft:
|
|
|
|
return QRectF(B2.x() - mHFlipSvgItem->boundingRect().width() - 5,
|
|
|
|
B2.y() + 5 + dy,
|
|
|
|
mHFlipSvgItem->boundingRect().width(),
|
|
|
|
mHFlipSvgItem->boundingRect().height());
|
|
|
|
case TopRight:
|
|
|
|
return QRectF(B2.x() + 5,
|
|
|
|
B2.y() + 5 + dy,
|
|
|
|
mHFlipSvgItem->boundingRect().width(),
|
|
|
|
mHFlipSvgItem->boundingRect().height());
|
|
|
|
case BottomRight:
|
|
|
|
return QRectF(B2.x() + 5,
|
|
|
|
B2.y() - mHFlipSvgItem->boundingRect().height() - 5 - dy,
|
|
|
|
mHFlipSvgItem->boundingRect().width(),
|
|
|
|
mHFlipSvgItem->boundingRect().height());
|
|
|
|
}
|
|
|
|
return QRectF(0,0,0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF UBGraphicsTriangle::vFlipRect() const
|
|
|
|
{
|
|
|
|
qreal dy = mCloseSvgItem->boundingRect().height() + 5;
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
return QRectF(B2.x() - mVFlipSvgItem->boundingRect().width() - 5,
|
|
|
|
B2.y() - mVFlipSvgItem->boundingRect().height() - 5 - dy,
|
|
|
|
mVFlipSvgItem->boundingRect().width(),
|
|
|
|
mVFlipSvgItem->boundingRect().height());
|
|
|
|
case TopLeft:
|
|
|
|
return QRectF(B2.x() - mVFlipSvgItem->boundingRect().width() - 5,
|
|
|
|
B2.y() + 5 + dy,
|
|
|
|
mVFlipSvgItem->boundingRect().width(),
|
|
|
|
mVFlipSvgItem->boundingRect().height());
|
|
|
|
case TopRight:
|
|
|
|
return QRectF(B2.x() + 5,
|
|
|
|
B2.y() + 5 + dy,
|
|
|
|
mVFlipSvgItem->boundingRect().width(),
|
|
|
|
mVFlipSvgItem->boundingRect().height());
|
|
|
|
case BottomRight:
|
|
|
|
return QRectF(B2.x() + 5,
|
|
|
|
B2.y() - mVFlipSvgItem->boundingRect().height() - 5 - dy,
|
|
|
|
mVFlipSvgItem->boundingRect().width(),
|
|
|
|
mVFlipSvgItem->boundingRect().height());
|
|
|
|
}
|
|
|
|
return QRectF(0,0,0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF UBGraphicsTriangle::rotateRect() const
|
|
|
|
{
|
|
|
|
QPointF p(C2);
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
p += QPointF(20, 5);
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
p += QPointF(20, -5 - mRotateSvgItem->boundingRect().height());
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
p += QPointF(-20 - mRotateSvgItem->boundingRect().width(), -5 - mRotateSvgItem->boundingRect().height());
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
p += QPointF(-20 - mRotateSvgItem->boundingRect().width(), 5);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return QRectF(p, QSizeF(mRotateSvgItem->boundingRect().size()));
|
|
|
|
}
|
|
|
|
|
|
|
|
QCursor UBGraphicsTriangle::resizeCursor1() const
|
|
|
|
{
|
|
|
|
return mResizeCursor1;
|
|
|
|
}
|
|
|
|
|
|
|
|
QCursor UBGraphicsTriangle::resizeCursor2() const
|
|
|
|
{
|
|
|
|
return mResizeCursor2;
|
|
|
|
}
|
|
|
|
|
|
|
|
QCursor UBGraphicsTriangle::flipCursor() const
|
|
|
|
{
|
|
|
|
return Qt::ArrowCursor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
|
|
|
lastRect = rect().toRect();
|
|
|
|
lastPos = sceneTransform().inverted().map(event->screenPos());
|
|
|
|
|
|
|
|
if (resize1Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
|
|
|
|
{
|
|
|
|
mResizing1 = true;
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (resize2Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
|
|
|
|
{
|
|
|
|
mResizing2 = true;
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if(rotateRect().contains(event->pos()))
|
|
|
|
{
|
|
|
|
mRotating = true;
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QGraphicsItem::mousePressEvent(event);
|
|
|
|
}
|
|
|
|
mShowButtons = false;
|
|
|
|
mCloseSvgItem->setVisible(false);
|
|
|
|
mHFlipSvgItem->setVisible(false);
|
|
|
|
mVFlipSvgItem->setVisible(false);
|
|
|
|
mRotateSvgItem->setVisible(mRotating);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!mResizing1 && !mResizing2 && !mRotating)
|
|
|
|
{
|
|
|
|
QGraphicsItem::mouseMoveEvent(event);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QPoint currPos = sceneTransform().inverted().map(event->screenPos());
|
|
|
|
|
|
|
|
if (mResizing1)
|
|
|
|
{
|
|
|
|
if (mOrientation == TopLeft || mOrientation == BottomLeft)
|
|
|
|
{
|
|
|
|
int deltaX = currPos.x() - lastPos.x();
|
|
|
|
if (lastRect.width() + deltaX < sMinWidth)
|
|
|
|
deltaX = sMinWidth - lastRect.width();
|
|
|
|
|
|
|
|
setRect(QRectF(lastRect.left(), lastRect.top(),
|
|
|
|
lastRect.width() + deltaX, lastRect.height()), mOrientation);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int deltaX = lastPos.x() - currPos.x();
|
|
|
|
if (lastRect.width() + deltaX < sMinWidth)
|
|
|
|
deltaX = sMinWidth - lastRect.width();
|
|
|
|
|
|
|
|
setRect(QRectF(lastRect.left() - deltaX, lastRect.top(),
|
|
|
|
lastRect.width() + deltaX, lastRect.height()), mOrientation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------//
|
|
|
|
|
|
|
|
if (mResizing2)
|
|
|
|
{
|
|
|
|
if (mOrientation == BottomRight || mOrientation == BottomLeft)
|
|
|
|
{
|
|
|
|
int deltaY = lastPos.y() - currPos.y();
|
|
|
|
if (lastRect.height() + deltaY < sMinHeight)
|
|
|
|
deltaY = sMinHeight - lastRect.height();
|
|
|
|
|
|
|
|
setRect(QRectF(lastRect.left(), lastRect.top() - deltaY,
|
|
|
|
lastRect.width(), lastRect.height() + deltaY), mOrientation);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int deltaY = currPos.y() - lastPos.y();
|
|
|
|
if (lastRect.height() + deltaY < sMinHeight)
|
|
|
|
deltaY = sMinHeight - lastRect.height();
|
|
|
|
|
|
|
|
setRect(QRectF(lastRect.left(), lastRect.top(),
|
|
|
|
lastRect.width(), lastRect.height() + deltaY), mOrientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------//
|
|
|
|
|
|
|
|
if (mRotating)
|
|
|
|
{
|
|
|
|
QLineF currentLine(rotationCenter(), event->pos());
|
|
|
|
QLineF lastLine(rotationCenter(), event->lastPos());
|
|
|
|
rotateAroundCenter(currentLine.angleTo(lastLine));
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------//
|
|
|
|
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
|
|
{
|
|
|
|
if (mResizing1 || mResizing2 || mRotating)
|
|
|
|
{
|
|
|
|
if (mRotating)
|
|
|
|
updateResizeCursor();
|
|
|
|
mResizing1 = false;
|
|
|
|
mResizing2 = false;
|
|
|
|
mRotating = false;
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else if (closeButtonRect().contains(event->pos()))
|
|
|
|
{
|
|
|
|
hide();
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
else if (hFlipRect().contains(event->pos()))
|
|
|
|
{
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
setOrientation(BottomRight);
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
setOrientation(BottomLeft);
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
setOrientation(TopRight);
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
setOrientation(TopLeft);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (vFlipRect().contains(event->pos()))
|
|
|
|
{
|
|
|
|
switch(mOrientation)
|
|
|
|
{
|
|
|
|
case BottomLeft:
|
|
|
|
setOrientation(TopLeft);
|
|
|
|
break;
|
|
|
|
case BottomRight:
|
|
|
|
setOrientation(TopRight);
|
|
|
|
break;
|
|
|
|
case TopLeft:
|
|
|
|
setOrientation(BottomLeft);
|
|
|
|
break;
|
|
|
|
case TopRight:
|
|
|
|
setOrientation(BottomRight);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QGraphicsItem::mouseReleaseEvent(event);
|
|
|
|
}
|
|
|
|
mShowButtons = true;
|
|
|
|
update();
|
|
|
|
if (scene())
|
|
|
|
scene()->setModified(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
|
|
|
{
|
|
|
|
UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
|
|
|
|
|
|
|
|
if (currentTool == UBStylusTool::Selector ||
|
|
|
|
currentTool == UBStylusTool::Play)
|
|
|
|
{
|
|
|
|
mCloseSvgItem->setParentItem(this);
|
|
|
|
|
|
|
|
mShowButtons = true;
|
|
|
|
mCloseSvgItem->setVisible(true);
|
|
|
|
mHFlipSvgItem->setVisible(true);
|
|
|
|
mVFlipSvgItem->setVisible(true);
|
|
|
|
mRotateSvgItem->setVisible(true);
|
|
|
|
|
|
|
|
if (resize1Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
|
|
|
|
setCursor(resizeCursor1());
|
|
|
|
else if(resize2Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
|
|
|
|
setCursor(resizeCursor2());
|
|
|
|
else if (closeButtonRect().contains(event->pos()))
|
|
|
|
setCursor(closeCursor());
|
|
|
|
else if (hFlipRect().contains(event->pos())
|
|
|
|
|| vFlipRect().contains(event->pos()))
|
|
|
|
setCursor(flipCursor());
|
|
|
|
else if (rotateRect().contains(event->pos()))
|
|
|
|
setCursor(rotateCursor());
|
|
|
|
else
|
|
|
|
setCursor(moveCursor());
|
|
|
|
|
|
|
|
event->accept();
|
|
|
|
update();
|
|
|
|
|
|
|
|
} else if (UBDrawingController::drawingController()->isDrawingTool()) {
|
|
|
|
setCursor(drawRulerLineCursor());
|
|
|
|
UBDrawingController::drawingController()->mActiveRuler = this;
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|
|
|
{
|
|
|
|
mResizing1 = mResizing2 = mRotating = false;
|
|
|
|
mShowButtons = false;
|
|
|
|
setCursor(Qt::ArrowCursor);
|
|
|
|
mCloseSvgItem->setVisible(false);
|
|
|
|
mVFlipSvgItem->setVisible(false);
|
|
|
|
mHFlipSvgItem->setVisible(false);
|
|
|
|
mRotateSvgItem->setVisible(false);
|
|
|
|
UBDrawingController::drawingController()->mActiveRuler = NULL;
|
|
|
|
event->accept();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
|
|
|
{
|
|
|
|
UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
|
|
|
|
|
|
|
|
if (currentTool == UBStylusTool::Selector ||
|
|
|
|
currentTool == UBStylusTool::Play)
|
|
|
|
{
|
|
|
|
mCloseSvgItem->setVisible(mShowButtons);
|
|
|
|
mVFlipSvgItem->setVisible(mShowButtons);
|
|
|
|
mHFlipSvgItem->setVisible(mShowButtons);
|
|
|
|
mRotateSvgItem->setVisible(mShowButtons);
|
|
|
|
|
|
|
|
if (resize1Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
|
|
|
|
setCursor(resizeCursor1());
|
|
|
|
else if (resize2Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
|
|
|
|
setCursor(resizeCursor2());
|
|
|
|
else if (closeButtonRect().contains(event->pos()))
|
|
|
|
setCursor(closeCursor());
|
|
|
|
else if (hFlipRect().contains(event->pos())
|
|
|
|
|| vFlipRect().contains(event->pos()))
|
|
|
|
setCursor(flipCursor());
|
|
|
|
else if (rotateRect().contains(event->pos()))
|
|
|
|
setCursor(rotateCursor());
|
|
|
|
else
|
|
|
|
setCursor(moveCursor());
|
|
|
|
|
|
|
|
event->accept();
|
|
|
|
} else if (UBDrawingController::drawingController()->isDrawingTool()) {
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void UBGraphicsTriangle::StartLine(const QPointF &scenePos, qreal width)
|
|
|
|
{
|
|
|
|
QPointF itemPos = mapFromScene(scenePos);
|
|
|
|
|
|
|
|
qreal y;
|
|
|
|
|
|
|
|
if (mOrientation == 0 || mOrientation == 1) {
|
|
|
|
y = rect().y() + rect().height() + width / 2;
|
|
|
|
} else if (mOrientation == 2 || mOrientation == 3) {
|
|
|
|
y = rect().y() - width / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (itemPos.x() < rect().x() + sLeftEdgeMargin)
|
|
|
|
itemPos.setX(rect().x() + sLeftEdgeMargin);
|
|
|
|
if (itemPos.x() > rect().x() + rect().width() - sLeftEdgeMargin)
|
|
|
|
itemPos.setX(rect().x() + rect().width() - sLeftEdgeMargin);
|
|
|
|
|
|
|
|
itemPos.setY(y);
|
|
|
|
itemPos = mapToScene(itemPos);
|
|
|
|
|
|
|
|
scene()->moveTo(itemPos);
|
|
|
|
scene()->drawLineTo(itemPos, width, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::DrawLine(const QPointF &scenePos, qreal width)
|
|
|
|
{
|
|
|
|
QPointF itemPos = mapFromScene(scenePos);
|
|
|
|
|
|
|
|
qreal y;
|
|
|
|
|
|
|
|
if (mOrientation == 0 || mOrientation == 1) {
|
|
|
|
y = rect().y() + rect().height() + width / 2;
|
|
|
|
} else if (mOrientation == 2 || mOrientation == 3) {
|
|
|
|
y = rect().y() - width / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (itemPos.x() < rect().x() + sLeftEdgeMargin)
|
|
|
|
itemPos.setX(rect().x() + sLeftEdgeMargin);
|
|
|
|
if (itemPos.x() > rect().x() + rect().width() - sLeftEdgeMargin)
|
|
|
|
itemPos.setX(rect().x() + rect().width() - sLeftEdgeMargin);
|
|
|
|
|
|
|
|
itemPos.setY(y);
|
|
|
|
itemPos = mapToScene(itemPos);
|
|
|
|
|
|
|
|
// We have to use "pointed" line for marker tool
|
|
|
|
scene()->drawLineTo(itemPos, width,
|
|
|
|
UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Marker);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UBGraphicsTriangle::EndLine()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|