From 3d8301cc0c2aefd037a0f9662a36eff44c9d870d Mon Sep 17 00:00:00 2001 From: Yimgo Date: Tue, 21 Aug 2012 11:17:59 +0200 Subject: [PATCH] introduced aristo tool. TODO: * nice icon * nice brush * fix draw with marker --- resources/images/toolPalette/aristoTool.png | Bin 0 -> 10832 bytes resources/sankore.qrc | 1 + src/board/UBBoardController.cpp | 5 + src/core/UB.h | 1 + src/domain/UBGraphicsScene.cpp | 17 + src/domain/UBGraphicsScene.h | 1 + src/tools/UBGraphicsAristo.cpp | 757 ++++++++++++++++++++ src/tools/UBGraphicsAristo.h | 165 +++++ src/tools/UBToolsManager.cpp | 6 + src/tools/UBToolsManager.h | 1 + src/tools/tools.pri | 17 +- 11 files changed, 963 insertions(+), 8 deletions(-) create mode 100644 resources/images/toolPalette/aristoTool.png create mode 100644 src/tools/UBGraphicsAristo.cpp create mode 100644 src/tools/UBGraphicsAristo.h diff --git a/resources/images/toolPalette/aristoTool.png b/resources/images/toolPalette/aristoTool.png new file mode 100644 index 0000000000000000000000000000000000000000..225c0b1e0724c0b40cb15fdb5c514688337ca48b GIT binary patch literal 10832 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 Gp#KAHn-~88 literal 0 HcmV?d00001 diff --git a/resources/sankore.qrc b/resources/sankore.qrc index d9263dbd..94ef9a07 100644 --- a/resources/sankore.qrc +++ b/resources/sankore.qrc @@ -166,6 +166,7 @@ images/toolPalette/triangleTool.png images/toolPalette/protractorTool.png images/toolPalette/compassTool.png + images/toolPalette/aristoTool.png images/toolPalette/maskTool.png images/toolPalette/magnifierTool.png images/extraPalette/blackout.png diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 9ccd5bba..cb2a1a3e 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1276,6 +1276,11 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QStri mActiveScene->addMask(pPos); UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); } + else if (sourceUrl.toString() == UBToolsManager::manager()->aristo.id) + { + mActiveScene->addAristo(pPos); + UBDrawingController::drawingController()->setStylusTool(UBStylusTool::Selector); + } else { showMessage(tr("Unknown tool type %1").arg(sourceUrl.toString())); diff --git a/src/core/UB.h b/src/core/UB.h index afc0f91e..c47c9c9b 100644 --- a/src/core/UB.h +++ b/src/core/UB.h @@ -145,6 +145,7 @@ struct UBGraphicsItemType TriangleItemType, MagnifierItemType, cacheItemType, + AristoItemType, groupContainerType, ToolWidgetItemType }; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 19a7e851..27abf659 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -39,6 +39,7 @@ #include "tools/UBGraphicsTriangle.h" #include "tools/UBGraphicsCurtainItem.h" #include "tools/UBGraphicsCache.h" +#include "tools/UBGraphicsAristo.h" #include "document/UBDocumentProxy.h" @@ -2071,6 +2072,22 @@ void UBGraphicsScene::addCompass(QPointF center) setModified(true); } +void UBGraphicsScene::addAristo(QPointF center) +{ + UBGraphicsAristo* aristo = new UBGraphicsAristo(); + mTools << aristo; + + aristo->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); + + addItem(aristo); + + QPointF itemSceneCenter = aristo->sceneBoundingRect().center(); + aristo->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); + + aristo->setVisible(true); + setModified(true); +} + void UBGraphicsScene::addCache() { UBGraphicsCache* cache = new UBGraphicsCache(); diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 027ef706..eae7db84 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -220,6 +220,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem void addCompass(QPointF center); void addTriangle(QPointF center); void addMagnifier(UBMagnifierParams params); + void addAristo(QPointF center); void addMask(const QPointF ¢er = QPointF()); void addCache(); diff --git a/src/tools/UBGraphicsAristo.cpp b/src/tools/UBGraphicsAristo.cpp new file mode 100644 index 00000000..0cdeb69f --- /dev/null +++ b/src/tools/UBGraphicsAristo.cpp @@ -0,0 +1,757 @@ +/* + * 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 +#include + +#include "tools/UBGraphicsAristo.h" +#include "core/UBApplication.h" +#include "board/UBBoardController.h" +#include "board/UBDrawingController.h" +#include "domain/UBGraphicsScene.h" + +#include "core/memcheck.h" + +const QRect UBGraphicsAristo::sDefaultRect = QRect(0, 0, 800, 400); +const UBGraphicsAristo::UBGraphicsAristoOrientation UBGraphicsAristo::sDefaultOrientation = UBGraphicsAristo::Bottom; + +UBGraphicsAristo::UBGraphicsAristo() + : UBAbstractDrawRuler() + , QGraphicsPolygonItem() + , angle(0) + , mResizing(false) + , mRotating(false) + , mMarking(false) + , mSpan(180) + , mStartAngle(0) + , mCurrentAngle(0) + + +{ + setRect(sDefaultRect, sDefaultOrientation); + + create(*this); + + mHFlipSvgItem = new QGraphicsSvgItem(":/images/vflipTool.svg", this); + mHFlipSvgItem->setVisible(false); + mHFlipSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + + mResizeSvgItem = new QGraphicsSvgItem(":/images/resizeTool.svg", this); + mResizeSvgItem->setVisible(false); + mResizeSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + + mRotateSvgItem = new QGraphicsSvgItem(":/images/rotateTool.svg", this); + mRotateSvgItem->setVisible(false); + mRotateSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + + mMarkerSvgItem = new QGraphicsSvgItem(":/images/angleMarker.svg", this); + mMarkerSvgItem->setVisible(false); + mMarkerSvgItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); +} + +UBGraphicsAristo::~UBGraphicsAristo() +{ +} + +UBItem* UBGraphicsAristo::deepCopy(void) const +{ + UBGraphicsAristo* copy = new UBGraphicsAristo(); + copyItemParameters(copy); + return copy; +} + +void UBGraphicsAristo::copyItemParameters(UBItem *copy) const +{ + UBGraphicsAristo* cp = dynamic_cast(copy); + if (cp) + { + /* TODO: copy all members */ + cp->setPos(this->pos()); + cp->setPolygon(this->polygon()); + cp->setTransform(this->transform()); + } +} + +void UBGraphicsAristo::setRect(qreal x, qreal y, qreal w, qreal h, UBGraphicsAristoOrientation orientation) +{ + QPolygonF polygon; + polygon << QPointF(x, y) << QPoint(x, y + h) << QPoint(x+w, y + h); + setPolygon(polygon); + + setOrientation(orientation); +} + +void UBGraphicsAristo::setOrientation(UBGraphicsAristoOrientation orientation) +{ + mOrientation = orientation; + calculatePoints(rect()); + + QPolygonF polygon; + polygon << A << B << C; + setPolygon(polygon); +} + +UBGraphicsScene* UBGraphicsAristo::scene() const +{ + return static_cast(QGraphicsPolygonItem::scene()); +} + +/* calculatePoints() is used to calculate polygon's apexes coordinates. + * This function handles orientation changes too. + */ +void UBGraphicsAristo::calculatePoints(const QRectF& r) +{ + switch(mOrientation) + { + case Bottom: + A.setX(r.left()); A.setY(r.top()); + B.setX(r.right()); B.setY(r.top()); + C.setX(r.center().x()); C.setY(A.y() + r.width() / 2); + break; + case Top: + A.setX(r.left()); A.setY(r.bottom()); + B.setX(r.right()); B.setY(r.bottom()); + C.setX(r.center().x()); C.setY(A.y() - r.width() / 2); + break; + } +} + +void UBGraphicsAristo::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + QPolygonF polygon; + + painter->setBrush(Qt::NoBrush); + painter->setPen(drawColor()); + + polygon << A << B << C; + painter->drawPolygon(polygon); + polygon.clear(); + + paintGraduations(painter); + + mCloseSvgItem->setPos(closeButtonRect().topLeft() + rotationCenter()); + mHFlipSvgItem->setPos(hFlipRect().topLeft() + rotationCenter()); + mRotateSvgItem->setPos(rotateRect().topLeft() + rotationCenter()); + mResizeSvgItem->setPos(resizeButtonRect().topLeft() + rotationCenter()); + + + paintMarker(painter); + mMarkerSvgItem->setVisible(true); +} + +QPainterPath UBGraphicsAristo::shape() const +{ + QPainterPath tShape; + QPolygonF tPolygon; + + tPolygon << A << B << C; + tShape.addPolygon(tPolygon); + tPolygon.clear(); + + return tShape; +} + +/* paintMarker() adjust marker button according to the current angle, draw the line allowing user to set precisely the angle, and draw the current angle's value. */ +void UBGraphicsAristo::paintMarker(QPainter *painter) +{ + /* adjusting marker button */ + mMarkerSvgItem->setPos(markerButtonRect().topLeft() + rotationCenter()); + mMarkerSvgItem->resetTransform(); + mMarkerSvgItem->translate(-markerButtonRect().left(), -markerButtonRect().top()); + mMarkerSvgItem->rotate(mCurrentAngle); + mMarkerSvgItem->translate(markerButtonRect().left(), markerButtonRect().top()); + + + qreal co = cos((mCurrentAngle) * PI/180); + qreal si = sin((mCurrentAngle) * PI/180); + + /* Setting point composing the line (from point C) which intersects the line we want to draw. */ + QPointF referencePoint; + if (mOrientation == Bottom) { + if ((int)mCurrentAngle % 360 < 90) + referencePoint = B; + else + referencePoint = A; + } + else if (mOrientation == Top) { + if ((int)mCurrentAngle % 360 < 270 && (int)mCurrentAngle % 360 > 0) + referencePoint = A; + else + referencePoint = B; + } + + /* getting intersection point to draw the wanted line */ + QLineF intersectedLine(rotationCenter(), QPointF(rotationCenter().x()+co, rotationCenter().y()+si)); + QPointF intersectionPoint; + if (intersectedLine.intersect(QLineF(referencePoint, C), &intersectionPoint)) + painter->drawLine(QLineF(intersectionPoint, rotationCenter())); + + /* drawing angle value */ + qreal rightAngle = mOrientation == Bottom ? mCurrentAngle : 360 - mCurrentAngle; + + + QString angleText = QString("%1°").arg(rightAngle, 0, 'f', 1); + + QFont font1 = painter->font(); +#ifdef Q_WS_MAC + font1.setPointSizeF(font1.pointSizeF() - 3); +#endif + QFontMetricsF fm1(font1); + + if (mOrientation == Bottom) + painter->drawText(rotationCenter().x() - fm1.width(angleText)/2 - radius()/8, rotationCenter().y() + radius()/8 - fm1.height()/2, fm1.width(angleText), fm1.height(), Qt::AlignCenter, angleText); + else + painter->drawText(rotationCenter().x() - fm1.width(angleText)/2 - radius()/8, rotationCenter().y() - radius()/8 - fm1.height()/2, fm1.width(angleText), fm1.height(), Qt::AlignCenter, angleText); + + +} + +/* paintGraduations() paints graduations on the ruler side (length graduations) and the two other sides (angle graduation) */ +void UBGraphicsAristo::paintGraduations(QPainter *painter) +{ + paintRulerGraduations(painter); + paintProtractorGraduations(painter); +} + +void UBGraphicsAristo::paintRulerGraduations(QPainter *painter) +{ + /* defining useful constants */ + const int centimeterGraduationHeight = 15; + const int halfCentimeterGraduationHeight = 10; + const int millimeterGraduationHeight = 5; + const int millimetersPerCentimeter = 10; + const int millimetersPerHalfCentimeter = 5; + + painter->save(); + painter->setFont(font()); + QFontMetricsF fontMetrics(painter->font()); + + /* Browsing milliters in half width of ruler side */ + for (int millimeters = 0; millimeters < (rect().width() / 2 - sLeftEdgeMargin - sRoundingRadius) / sPixelsPerMillimeter; millimeters++) + { + /* defining graduationHeight ; values are different to draw bigger lines if millimiter considered is a centimeter or a half centimeter */ + int graduationHeight = (0 == millimeters % millimetersPerCentimeter) ? + centimeterGraduationHeight : + ((0 == millimeters % millimetersPerHalfCentimeter) ? + halfCentimeterGraduationHeight : millimeterGraduationHeight); + + /* correcting graduationHeight: draw the line in the other direction in case ruler is top-oriented, to stay inside the tool and inside the rect */ + graduationHeight = mOrientation == Bottom ? graduationHeight : - graduationHeight; + + /* drawing graduation to the left and to the right of origin, which is the center of graduated side */ + painter->drawLine(QLine(rotationCenter().x() + sPixelsPerMillimeter * millimeters, rotationCenter().y(), rotationCenter().x() + sPixelsPerMillimeter * millimeters, rotationCenter().y() + graduationHeight)); + if (millimeters != 0) + painter->drawLine(QLine(rotationCenter().x() - sPixelsPerMillimeter * millimeters, rotationCenter().y(), rotationCenter().x() - sPixelsPerMillimeter * millimeters, rotationCenter().y() + graduationHeight)); + + /* drawing associated value if considered graduation is a centimeter */ + if (0 == millimeters % millimetersPerCentimeter) + { + /* defining graduation value */ + QString text = QString("%1").arg((int)(millimeters / millimetersPerCentimeter)); + + /* staying inside polygon */ + if (rotationCenter().x() + sPixelsPerMillimeter * millimeters + fontMetrics.width(text) / 2 < rect().right()) + { + qreal textWidth = fontMetrics.width(text); + qreal textHeight = fontMetrics.tightBoundingRect(text).height() + 5; + + /* text y-coordinate is different according to tool's orientation */ + qreal textY = mOrientation == Bottom ? rect().top() + 5 + centimeterGraduationHeight : rect().bottom() - 5 - centimeterGraduationHeight + graduationHeight; + + /* if text's rect is not out of polygon's bounds, drawing value below or above graduation */ + QPointF intersectionPoint; + + bool paint = false; + + if (mOrientation == Bottom && QLineF(QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters - textWidth / 2, rotationCenter().y()), QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters - textWidth / 2, textY + textHeight)).intersect(QLineF(A, C), &intersectionPoint) != QLineF::BoundedIntersection && QLineF(QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters + textWidth / 2, rotationCenter().y()), QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters + textWidth / 2, textY + textHeight)).intersect(QLineF(A, C), &intersectionPoint) != QLineF::BoundedIntersection) { + paint = true; + } + else if (mOrientation == Top && QLineF(QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters - textWidth / 2, rotationCenter().y()), QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters - textWidth / 2, textY - textHeight)).intersect(QLineF(A, C), &intersectionPoint) != QLineF::BoundedIntersection && QLineF(QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters + textWidth / 2, rotationCenter().y()), QPointF(rotationCenter().x() - sPixelsPerMillimeter * millimeters + textWidth / 2, textY - textHeight)).intersect(QLineF(A, C), &intersectionPoint) != QLineF::BoundedIntersection) { + paint = true; + } + + if (paint) { + painter->drawText( + QRectF(rotationCenter().x() + sPixelsPerMillimeter * millimeters - textWidth / 2, textY, textWidth, textHeight), + Qt::AlignVCenter, text); + if (millimeters != 0) + painter->drawText( + QRectF(rotationCenter().x() - sPixelsPerMillimeter * millimeters - textWidth / 2, textY, textWidth, textHeight), + Qt::AlignVCenter, text); + } + } + } + } + painter->restore(); +} + +void UBGraphicsAristo::paintProtractorGraduations(QPainter* painter) +{ + /* defining useful constants */ + const int tenDegreeGraduationLength = 15; + const int fiveDegreeGraduationLength = 10; + const int oneDegreeGraduationLength = 5; + + painter->save(); + + QFont font1 = painter->font(); +#ifdef Q_WS_MAC + font1.setPointSizeF(font1.pointSizeF() - 3); +#endif + QFontMetricsF fm1(font1); + + //Font for internal arc + QFont font2 = painter->font(); + font2.setPointSizeF(font1.pointSizeF()/1.5); + QFontMetricsF fm2(font2); + + /* defining virtual arc diameter */ + qreal rad = radius(); + + QPointF center = rotationCenter(); + + /* browsing angles */ + for (int angle = 1; angle < mSpan; angle++) + { + int graduationLength = (0 == angle % 10) ? tenDegreeGraduationLength : ((0 == angle % 5) ? fiveDegreeGraduationLength : oneDegreeGraduationLength); + + qreal co = cos(((qreal)angle + mStartAngle) * PI/180); + qreal si = sin(((qreal)angle + mStartAngle) * PI/180); + + /* inverse sinus according to the orientation, to draw graduations on the polygon */ + si = mOrientation == Bottom ? -si : si; + + /* drawing the graduation around the virtual arc */ + if (angle >= sArcAngleMargin && angle <= mSpan - sArcAngleMargin) + painter->drawLine(QLineF(QPointF(center.x()+ rad/2*co, center.y() - rad/2*si), + QPointF(center.x()+ (rad/2 + graduationLength)*co, + center.y() - (rad/2 + graduationLength)*si))); + + + QPointF intersectionPoint; + QLineF referenceLine; + if (angle < 90) + referenceLine.setP1(B); + else + referenceLine.setP1(A); + referenceLine.setP2(C); + + /* if angle is 10-multiple, drawing it's value, rotated to be easily red */ + if (0 == angle % 10) { + QString grad = QString("%1").arg((int)(angle)); + QString grad2 = QString("%1").arg((int)mSpan - angle); + + painter->setFont(font2); + + painter->save(); + painter->translate(center.x() + (rad/2 + graduationLength*1.5)*co, center.y() - (rad/2 + graduationLength*1.5)*si); + int degrees = mOrientation == Bottom ? angle : -angle; + painter->rotate(-90 + degrees); + painter->drawText(- fm2.width(grad)/2, - fm2.height()/2, fm2.width(grad), fm2.height(), Qt::AlignCenter, grad); + painter->restore(); + + painter->setFont(font1); + + + /* drawing the graduation near tool's side */ + if (QLineF(QPointF(center.x()+ rad/2*co, center.y() - rad/2*si), + QPointF(center.x()+ (rad/2 + graduationLength)*co, + center.y() - (rad/2 + graduationLength)*si)).intersect(referenceLine, &intersectionPoint) == QLineF::UnboundedIntersection) + + painter->drawLine(QLineF(QPointF(center.x() + (rad/2 + graduationLength*1.5 + fm2.width(grad)/2)*co, + center.y() - (rad/2 + graduationLength*1.5 + fm2.height()/2)*si), + intersectionPoint)); + + } + + /* drawing the graduation near tool's side */ + else + if (QLineF(QPointF(center.x()+ rad/2*co, center.y() - rad/2*si), + QPointF(center.x()+ (rad/2 + graduationLength)*co, + center.y() - (rad/2 + graduationLength)*si)).intersect(referenceLine, &intersectionPoint) == QLineF::UnboundedIntersection) + + painter->drawLine(QLineF(QPointF(intersectionPoint.x() - (graduationLength*1.5)*co, + intersectionPoint.y() + (graduationLength*1.5)*si), + intersectionPoint)); + } + + painter->restore(); +} + + +void UBGraphicsAristo::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 UBGraphicsAristo::rotateAroundCenter(QTransform& transform, QPointF center) +{ + transform.translate(center.x(), center.y()); + transform.rotate(angle); + transform.translate(- center.x(), - center.y()); +} + +void UBGraphicsAristo::resize(qreal factor) +{ + prepareGeometryChange(); + translate(rotationCenter().x(), rotationCenter().y()); + scale(factor, factor); + translate(-rotationCenter().x(), -rotationCenter().y()); +} + + +QPointF UBGraphicsAristo::rotationCenter() const +{ + return QPointF((A.x() + B.x()) / 2, (A.y() + B.y()) / 2); +} + +QRectF UBGraphicsAristo::closeButtonRect() const +{ + qreal y = radius() / 4 + hFlipRect().height() + 3 + rotateRect().height() + 3; + if (mOrientation == Top) + y = -y; + return QRectF(- mCloseSvgItem->boundingRect().width() / 2, y, mCloseSvgItem->boundingRect().width(), mCloseSvgItem->boundingRect().height()); +} + +QRectF UBGraphicsAristo::resizeButtonRect() const +{ + return QRectF((B - rotationCenter()).x() - 100 - mResizeSvgItem->boundingRect().width()/2, - mResizeSvgItem->boundingRect().height()/2, mResizeSvgItem->boundingRect().width(), mResizeSvgItem->boundingRect().height()); +} + +QRectF UBGraphicsAristo::hFlipRect() const +{ + qreal y = radius() / 4; + if (mOrientation == Top) + y = -y; + + return QRectF(- mHFlipSvgItem->boundingRect().width() / 2, y, mHFlipSvgItem->boundingRect().width(), mHFlipSvgItem->boundingRect().height()); +} + +QRectF UBGraphicsAristo::rotateRect() const +{ + qreal y = radius() / 4 + hFlipRect().height() + 3; + if (mOrientation == Top) + y = -y; + return QRectF(- mRotateSvgItem->boundingRect().width() / 2, y, mRotateSvgItem->boundingRect().width(), mRotateSvgItem->boundingRect().height()); + +} + +QRectF UBGraphicsAristo::markerButtonRect() const +{ + return QRectF (radius()/2 - mMarkerSvgItem->boundingRect().width(), - mMarkerSvgItem->boundingRect().height()/2, mMarkerSvgItem->boundingRect().width(), mMarkerSvgItem->boundingRect().height()); +} + +QCursor UBGraphicsAristo::flipCursor() const +{ + return Qt::ArrowCursor; +} + +QCursor UBGraphicsAristo::resizeCursor() const +{ + return Qt::ArrowCursor; +} + +QCursor UBGraphicsAristo::markerCursor() const +{ + return Qt::ArrowCursor; +} + +void UBGraphicsAristo::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + switch (toolFromPos(event->pos())) { + case Rotate: + mRotating = true; + event->accept(); + break; + case Resize: + mResizing = true; + event->accept(); + break; + case MoveMarker: + mMarking = true; + event->accept(); + break; + default: + QGraphicsItem::mousePressEvent(event); + break; + } + + mShowButtons = false; + mHFlipSvgItem->setVisible(false); + mCloseSvgItem->setVisible(false); + mRotateSvgItem->setVisible(mRotating); + mResizeSvgItem->setVisible(mResizing); + update(); +} + +void UBGraphicsAristo::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + + if (!mResizing && !mRotating && !mMarking) + { + QGraphicsItem::mouseMoveEvent(event); + } + else + { + QLineF currentLine(rotationCenter(), event->pos()); + QLineF lastLine(rotationCenter(), event->lastPos()); + + if (mRotating) { + + rotateAroundCenter(currentLine.angleTo(lastLine)); + } + else if (mResizing) { + QPointF delta = event->pos() - event->lastPos(); + setRect(QRectF(rect().topLeft(), QSizeF(rect().width() + delta.x(), rect().height() + delta.x() / 2)), mOrientation); + } + else if(mMarking) { + qreal angle = currentLine.angleTo(lastLine); + + mCurrentAngle += angle; + mCurrentAngle -= (int)(mCurrentAngle/360)*360; + + if (mOrientation == Bottom) { + if (mCurrentAngle >= 270) + mCurrentAngle = 0; + else if (mCurrentAngle > 180) + mCurrentAngle = 180; + } + else if (mOrientation == Top) { + if (mCurrentAngle < 90) + mCurrentAngle = 360; + else if (mCurrentAngle < 180) + mCurrentAngle = 180; + } + update(); + } + + event->accept(); + } +} + +void UBGraphicsAristo::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (mResizing || mRotating || mMarking) + { + mResizing = false; + mRotating = false; + mMarking = false; + event->accept(); + } + else + { + switch (toolFromPos(event->pos())) { + case Close : + hide(); + emit hidden(); + break; + case HorizontalFlip: + /* substracting difference to zero [2pi] twice, to obtain the desired angle */ + mCurrentAngle -= 2 * (mCurrentAngle - (int)(mCurrentAngle/360)*360) - 360; + /* setting new orientation */ + switch(mOrientation) { + case Bottom: + setOrientation(Top); + break; + case Top: + setOrientation(Bottom); + break; + } + default: + QGraphicsItem::mouseReleaseEvent(event); + break; + } + } + + mShowButtons = true; + update(); + if (scene()) + scene()->setModified(true); +} + +void UBGraphicsAristo::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool (); + + if (currentTool == UBStylusTool::Selector) { + mShowButtons = true; + mHFlipSvgItem->setVisible(true); + mRotateSvgItem->setVisible(true); + mResizeSvgItem->setVisible(true); + mCloseSvgItem->setVisible(true); + + switch (toolFromPos(event->pos())) { + case HorizontalFlip: + setCursor(flipCursor()); + break; + case Rotate: + setCursor(rotateCursor()); + break; + case Resize: + setCursor(resizeCursor()); + break; + case MoveMarker: + setCursor(markerCursor()); + break; + case Close: + setCursor(closeCursor()); + break; + default: + setCursor(moveCursor()); + break; + } + + event->accept(); + update(); + + } else if (UBDrawingController::drawingController()->isDrawingTool()) { + setCursor(drawRulerLineCursor()); + UBDrawingController::drawingController()->mActiveRuler = this; + event->accept(); + } +} + +void UBGraphicsAristo::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + mShowButtons = false; + setCursor(Qt::ArrowCursor); + mHFlipSvgItem->setVisible(false); + mRotateSvgItem->setVisible(false); + mResizeSvgItem->setVisible(false); + mCloseSvgItem->setVisible(false); + UBDrawingController::drawingController()->mActiveRuler = NULL; + event->accept(); + update(); +} + +void UBGraphicsAristo::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool (); + + if (currentTool == UBStylusTool::Selector) + { + mShowButtons = true; + mHFlipSvgItem->setVisible(true); + mRotateSvgItem->setVisible(true); + mResizeSvgItem->setVisible(true); + mCloseSvgItem->setVisible(true); + + switch (toolFromPos(event->pos())) { + case HorizontalFlip: + setCursor(flipCursor()); + break; + case Rotate: + setCursor(rotateCursor()); + break; + case Resize: + setCursor(resizeCursor()); + break; + case MoveMarker: + setCursor(markerCursor()); + break; + case Close: + setCursor(closeCursor()); + break; + default: + setCursor(moveCursor()); + break; + } + + event->accept(); + } + else if (UBDrawingController::drawingController()->isDrawingTool()) + event->accept(); +} + +/* + * toolfrompos() returns the item type corresponding to the given position. + * This method is used to reduce the amount of code in each event function and improve class' maintainability. + * pos: event's position ; a rotation is done to counter elements rotation, like the marker button. + */ +UBGraphicsAristo::Tool UBGraphicsAristo::toolFromPos(QPointF pos) +{ + pos = pos - rotationCenter(); + + qreal rotationAngle = mOrientation == Bottom ? - mCurrentAngle : 360 * (int)(mCurrentAngle / 360 + 1) - mCurrentAngle; + + QTransform t; + t.rotate(rotationAngle); + QPointF p2 = t.map(pos); + + if (resizeButtonRect().contains(pos)) + return Resize; + else if (closeButtonRect().contains(pos)) + return Close; + else if (rotateRect().contains(pos)) + return Rotate; + else if (markerButtonRect().contains(p2)) + return MoveMarker; + else if (hFlipRect().contains(pos)) + return HorizontalFlip; + else if (shape().contains(pos)) + return Move; + else + return None; +} + +void UBGraphicsAristo::StartLine(const QPointF &scenePos, qreal width) +{ + QPointF itemPos = mapFromScene(scenePos); + + qreal y; + + y = rotationCenter().y(); + + 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 UBGraphicsAristo::DrawLine(const QPointF &scenePos, qreal width) +{ + QPointF itemPos = mapFromScene(scenePos); + + qreal y; + + y = rotationCenter().y(); + + 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 UBGraphicsAristo::EndLine() +{ +} diff --git a/src/tools/UBGraphicsAristo.h b/src/tools/UBGraphicsAristo.h new file mode 100644 index 00000000..ee791d74 --- /dev/null +++ b/src/tools/UBGraphicsAristo.h @@ -0,0 +1,165 @@ +/* + * 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 . + */ + +#ifndef UBGRAPHICSARISTO_H_ +#define UBGRAPHICSARISTO_H_ + +#include +#include +#include + +#include "core/UB.h" +#include "domain/UBItem.h" +#include "tools/UBAbstractDrawRuler.h" + + +class UBGraphicsScene; +class UBItem; + +class UBGraphicsAristo : public UBAbstractDrawRuler, public QGraphicsPolygonItem, public UBItem +{ + Q_OBJECT + + public: + UBGraphicsAristo(); + virtual ~UBGraphicsAristo(); + + enum { Type = UBGraphicsItemType::AristoItemType }; + enum Tool {None, Move, Resize, Rotate, Close, MoveMarker, HorizontalFlip}; + + virtual int type() const + { + return Type; + } + + virtual UBItem* deepCopy(void) const; + virtual void copyItemParameters(UBItem *copy) const; + + virtual void StartLine(const QPointF& scenePos, qreal width); + virtual void DrawLine(const QPointF& position, qreal width); + virtual void EndLine(); + + enum UBGraphicsAristoOrientation + { + Bottom = 0, + Top + }; + + static UBGraphicsAristoOrientation orientationFromStr(QStringRef& str) + { + if (str == "Bottom") return Bottom; + if (str == "Top") return Top; + return sDefaultOrientation; + } + static QString orientationToStr(UBGraphicsAristoOrientation orientation) + { + QString result; + if (orientation == 0) result = "Bottom"; + else if (orientation == 1) result = "Top"; + + return result; + } + + void setRect(const QRectF &rect, UBGraphicsAristoOrientation orientation) + { + setRect(rect.x(), rect.y(), rect.width(), rect.height(), orientation); + } + + void setRect(qreal x, qreal y, qreal w, qreal h, UBGraphicsAristoOrientation orientation); + + void setOrientation(UBGraphicsAristoOrientation orientation); + + UBGraphicsAristoOrientation getOrientation() const {return mOrientation;} + + QRectF rect() const {return boundingRect();} + + UBGraphicsScene* scene() const; + + protected: + + virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *styleOption, QWidget *widget); + virtual QPainterPath shape() const; + + virtual void rotateAroundCenter(qreal angle); + virtual void resize(qreal factor); + + virtual QPointF rotationCenter() const; + + virtual QRectF closeButtonRect() const; + QRectF resizeButtonRect () const; + QRectF hFlipRect() const; + QRectF rotateRect() const; + QRectF markerButtonRect() const; + + QCursor flipCursor() const; + QCursor resizeCursor() const; + QCursor markerCursor() const; + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + + private: + UBGraphicsAristo::Tool toolFromPos(QPointF pos); + QTransform calculateRotationTransform(); + qreal angle; + + void rotateAroundCenter(QTransform& transform, QPointF center); + + bool mResizing; + bool mRotating; + bool mMarking; + QRect lastRect; + qreal mSpan; + + // Coordinates are transformed.... + QPoint lastPos; + QGraphicsSvgItem* mHFlipSvgItem; + QGraphicsSvgItem* mRotateSvgItem; + QGraphicsSvgItem* mResizeSvgItem; + QGraphicsSvgItem* mMarkerSvgItem; + qreal mStartAngle; + qreal mCurrentAngle; + + static const QRect sDefaultRect; + static const UBGraphicsAristoOrientation sDefaultOrientation; + + void paintGraduations(QPainter *painter); + void paintRulerGraduations(QPainter *painter); + void paintProtractorGraduations(QPainter* painter); + void paintMarker(QPainter *painter); + inline qreal radius () const + { + return sqrt(((B.x() - A.x())*(B.x() - A.x()))+((B.y() - A.y())*(B.y() - A.y()))) * 9 / 16 - 20; + } + + + UBGraphicsAristoOrientation mOrientation; + + void calculatePoints(const QRectF& rect); + + QPointF A, B, C; + + static const int d = 70; // width of triangle border + static const int sArrowLength = 30; + static const int sMinWidth = 380; + static const int sMinHeight = 200; + static const int sArcAngleMargin = 5; +}; + +#endif /* UBGRAPHICSARISTO_H_ */ diff --git a/src/tools/UBToolsManager.cpp b/src/tools/UBToolsManager.cpp index 95b40eec..d30e4fa1 100644 --- a/src/tools/UBToolsManager.cpp +++ b/src/tools/UBToolsManager.cpp @@ -91,6 +91,12 @@ UBToolsManager::UBToolsManager(QObject *parent) mDescriptors << cache; // -------------------------------------------------------------------------------- + aristo.id = "uniboardTool://uniboard.mnemis.com/aristo"; + aristo.icon = QPixmap(":/images/toolPalette/aristoTool.png"); + aristo.label = tr("Aristo"); + aristo.version = "1.0"; + mToolsIcon.insert(aristo.id, ":/images/toolPalette/aristoTool.png"); + mDescriptors << aristo; } UBToolsManager::~UBToolsManager() diff --git a/src/tools/UBToolsManager.h b/src/tools/UBToolsManager.h index eee12d61..410b224f 100644 --- a/src/tools/UBToolsManager.h +++ b/src/tools/UBToolsManager.h @@ -76,6 +76,7 @@ class UBToolsManager : public QObject UBToolDescriptor triangle; UBToolDescriptor magnifier; UBToolDescriptor cache; + UBToolDescriptor aristo; QString iconFromToolId(QString id) { return mToolsIcon.value(id);} diff --git a/src/tools/tools.pri b/src/tools/tools.pri index 90e69659..0196f84d 100644 --- a/src/tools/tools.pri +++ b/src/tools/tools.pri @@ -1,20 +1,21 @@ - -HEADERS += src/tools/UBGraphicsRuler.h \ - src/tools/UBGraphicsTriangle.h \ +HEADERS += src/tools/UBGraphicsRuler.h \ + src/tools/UBGraphicsTriangle.h \ src/tools/UBGraphicsProtractor.h \ src/tools/UBGraphicsCompass.h \ + src/tools/UBGraphicsAristo.h \ src/tools/UBToolsManager.h \ src/tools/UBGraphicsCurtainItem.h \ src/tools/UBGraphicsCurtainItemDelegate.h \ src/tools/UBAbstractDrawRuler.h \ - src/tools/UBGraphicsCache.h - -SOURCES += src/tools/UBGraphicsRuler.cpp \ - src/tools/UBGraphicsTriangle.cpp \ + src/tools/UBGraphicsCache.h + +SOURCES += src/tools/UBGraphicsRuler.cpp \ + src/tools/UBGraphicsTriangle.cpp \ src/tools/UBGraphicsProtractor.cpp \ src/tools/UBGraphicsCompass.cpp \ + src/tools/UBGraphicsAristo.cpp \ src/tools/UBToolsManager.cpp \ src/tools/UBGraphicsCurtainItem.cpp \ src/tools/UBGraphicsCurtainItemDelegate.cpp \ src/tools/UBAbstractDrawRuler.cpp \ - src/tools/UBGraphicsCache.cpp + src/tools/UBGraphicsCache.cpp