[TD]fix balloon drag on rotated view (fix #15726)
This commit is contained in:
committed by
Yorik van Havre
parent
1be41b68a2
commit
e88b1b49c9
@@ -96,6 +96,7 @@ public:
|
||||
virtual bool checkFit() const;
|
||||
virtual bool checkFit(DrawPage*) const;
|
||||
virtual void setPosition(double x, double y, bool force = false);
|
||||
virtual Base::Vector3d getPosition() const { return Base::Vector3d(X.getValue(), Y.getValue(), 0.0); }
|
||||
virtual bool keepUpdated(void);
|
||||
|
||||
boost::signals2::signal<void (const DrawView*)> signalGuiPaint;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Tools.h>
|
||||
#include <Mod/TechDraw/App/ArrowPropEnum.h>
|
||||
@@ -205,6 +206,11 @@ void QGIBalloonLabel::setLabelCenter()
|
||||
posY = y() + m_labelText->boundingRect().height() / 2.;
|
||||
}
|
||||
|
||||
Base::Vector3d QGIBalloonLabel::getLabelCenter() const
|
||||
{
|
||||
return Base::Vector3d(posX, posY, 0.0);
|
||||
}
|
||||
|
||||
void QGIBalloonLabel::setFont(QFont font) { m_labelText->setFont(font); }
|
||||
|
||||
void QGIBalloonLabel::setDimString(QString text)
|
||||
@@ -381,7 +387,6 @@ void QGIViewBalloon::setViewPartFeature(TechDraw::DrawViewBalloon* balloonFeat)
|
||||
|
||||
void QGIViewBalloon::updateView(bool update)
|
||||
{
|
||||
// Base::Console().Message("QGIVB::updateView()\n");
|
||||
Q_UNUSED(update);
|
||||
auto balloon(dynamic_cast<TechDraw::DrawViewBalloon*>(getViewObject()));
|
||||
if (!balloon) {
|
||||
@@ -406,7 +411,6 @@ void QGIViewBalloon::updateView(bool update)
|
||||
//update the bubble contents
|
||||
void QGIViewBalloon::updateBalloon(bool obtuse)
|
||||
{
|
||||
// Base::Console().Message("QGIVB::updateBalloon()\n");
|
||||
(void)obtuse;
|
||||
const auto balloon(dynamic_cast<TechDraw::DrawViewBalloon*>(getViewObject()));
|
||||
if (!balloon) {
|
||||
@@ -459,7 +463,9 @@ void QGIViewBalloon::balloonLabelDragged(bool ctrl)
|
||||
if (!m_dragInProgress) {//first drag movement
|
||||
m_dragInProgress = true;
|
||||
if (ctrl) {//moving whole thing, remember Origin offset from Bubble
|
||||
m_saveOffset = dvb->getOriginOffset();
|
||||
m_saveOriginOffset = dvb->getOriginOffset();
|
||||
m_saveOrigin = DU::toVector3d(arrow->pos());
|
||||
m_savePosition = DU::toVector3d(balloonLabel->pos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,6 +479,10 @@ void QGIViewBalloon::balloonLabelDragged(bool ctrl)
|
||||
// redraw the balloon at the new position
|
||||
// note that we don't store the new position to the X/Y properties
|
||||
// since the dragging is not yet finished
|
||||
// TODO: we don't need to redraw if the graphic is not changing (other than location).
|
||||
// all of the balloon components (box, text, line, arrow, etc) would have to be placed
|
||||
// into a QGraphicsItemGroup (or made children of a single QGI) in order to move them in
|
||||
// sync
|
||||
drawBalloon(true);
|
||||
}
|
||||
}
|
||||
@@ -488,12 +498,14 @@ void QGIViewBalloon::balloonLabelDragFinished()
|
||||
|
||||
double scale = 1.0;
|
||||
DrawView* balloonParent = getSourceView();
|
||||
if (balloonParent) {
|
||||
scale = balloonParent->getScale();
|
||||
if (!balloonParent) {
|
||||
return;
|
||||
}
|
||||
scale = balloonParent->getScale();
|
||||
|
||||
//set feature position (x, y) from graphic position
|
||||
double x = Rez::appX(balloonLabel->X() / scale), y = Rez::appX(balloonLabel->Y() / scale);
|
||||
double x = Rez::appX(balloonLabel->X() / scale);
|
||||
double y = Rez::appX(balloonLabel->Y() / scale);
|
||||
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Drag Balloon"));
|
||||
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.X = %f",
|
||||
dvb->getNameInDocument(), x);
|
||||
@@ -502,18 +514,27 @@ void QGIViewBalloon::balloonLabelDragFinished()
|
||||
|
||||
// for the case that origin was also dragged, calc new origin and update feature
|
||||
if (m_originDragged) {
|
||||
Base::Vector3d pos(x, -y, 0.0);
|
||||
Base::Vector3d newOrg = pos - m_saveOffset;
|
||||
auto originGui = arrowPosInDrag(); // Qt rotated
|
||||
auto originApp = originGui / scale; // Qt rotated unscaled
|
||||
originApp = Rez::appX(DU::invertY(originApp)); // App rotated
|
||||
|
||||
auto originAppUnrotated = originApp;
|
||||
auto rotationDeg = balloonParent->Rotation.getValue();
|
||||
if (rotationDeg != 0) {
|
||||
originAppUnrotated.RotateZ(Base::toRadians(-rotationDeg));
|
||||
}
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.OriginX = %f",
|
||||
dvb->getNameInDocument(), newOrg.x);
|
||||
dvb->getNameInDocument(), originAppUnrotated.x);
|
||||
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.OriginY = %f",
|
||||
dvb->getNameInDocument(), newOrg.y);
|
||||
dvb->getNameInDocument(), originAppUnrotated.y);
|
||||
}
|
||||
|
||||
Gui::Command::commitCommand();
|
||||
|
||||
m_dragInProgress = false;
|
||||
m_originDragged = false;
|
||||
drawBalloon(false);
|
||||
}
|
||||
|
||||
//from QGVP::mouseReleaseEvent - pos = eventPos in scene coords?
|
||||
@@ -579,14 +600,18 @@ void QGIViewBalloon::placeBalloon(QPointF pos)
|
||||
|
||||
void QGIViewBalloon::draw()
|
||||
{
|
||||
// Base::Console().Message("QGIVB::draw()\n");
|
||||
// just redirect
|
||||
drawBalloon(false);
|
||||
}
|
||||
|
||||
void QGIViewBalloon::drawBalloon(bool dragged)
|
||||
{
|
||||
// Base::Console().Message("QGIVB::drawBalloon(%d)\n", dragged);
|
||||
if ((!dragged) && m_dragInProgress) {
|
||||
// TODO there are 2 drag status variables. m_dragInProgress appears to be the one to use?
|
||||
// dragged shows false while drag is still in progress.
|
||||
return;
|
||||
}
|
||||
|
||||
prepareGeometryChange();
|
||||
|
||||
TechDraw::DrawViewBalloon* balloon = dynamic_cast<TechDraw::DrawViewBalloon*>(getViewObject());
|
||||
@@ -595,6 +620,10 @@ void QGIViewBalloon::drawBalloon(bool dragged)
|
||||
//nothing to draw, don't try
|
||||
return;
|
||||
}
|
||||
if (balloon->isRestoring()) {
|
||||
// don't try to draw yet
|
||||
return;
|
||||
}
|
||||
|
||||
TechDraw::DrawView* refObj = balloon->getParentView();
|
||||
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
|
||||
@@ -607,32 +636,14 @@ void QGIViewBalloon::drawBalloon(bool dragged)
|
||||
|
||||
double textWidth = balloonLabel->getDimText()->boundingRect().width();
|
||||
double textHeight = balloonLabel->getDimText()->boundingRect().height();
|
||||
float x, y, arrowTipX, arrowTipY;
|
||||
Base::Vector3d arrowTip{balloon->OriginX.getValue(), balloon->OriginY.getValue(), 0.0};
|
||||
// when not dragging take the X/Y properties otherwise the current label position
|
||||
if (!dragged) {
|
||||
x = Rez::guiX(balloon->X.getValue() * refObj->getScale());
|
||||
y = Rez::guiX(balloon->Y.getValue() * refObj->getScale());
|
||||
arrowTipX = Rez::guiX(balloon->OriginX.getValue() * refObj->getScale());
|
||||
arrowTipY = -Rez::guiX(balloon->OriginY.getValue() * refObj->getScale());
|
||||
}
|
||||
else {
|
||||
x = balloonLabel->X();
|
||||
y = -balloonLabel->Y();
|
||||
if (m_originDragged) {
|
||||
double scale = Rez::guiX(refObj->getScale());
|
||||
Base::Vector3d pos(x / scale, y / scale, 0.0);
|
||||
Base::Vector3d newOrg = pos - m_saveOffset;
|
||||
arrowTip = newOrg;
|
||||
arrowTipX = newOrg.x * scale;
|
||||
arrowTipY = -newOrg.y * scale;
|
||||
}
|
||||
else {
|
||||
arrowTipX = Rez::guiX(balloon->OriginX.getValue() * refObj->getScale());
|
||||
arrowTipY = -Rez::guiX(balloon->OriginY.getValue() * refObj->getScale());
|
||||
}
|
||||
}
|
||||
Base::Vector3d lblCenter(x, -y, 0.0);
|
||||
|
||||
float arrowTipX;
|
||||
Base::Vector3d arrowTipPosInParent;
|
||||
bool isDragging = dragged || m_dragInProgress;
|
||||
Base::Vector3d labelPos;
|
||||
getBalloonPoints(balloon, refObj, isDragging, labelPos, arrowTipPosInParent);
|
||||
arrowTipX = arrowTipPosInParent.x;
|
||||
Base::Vector3d lblCenter(labelPos.x, -labelPos.y, 0.0);
|
||||
|
||||
if (balloon->isLocked()) {
|
||||
balloonLabel->setFlag(QGraphicsItem::ItemIsMovable, false);
|
||||
@@ -782,24 +793,20 @@ void QGIViewBalloon::drawBalloon(bool dragged)
|
||||
}
|
||||
else {
|
||||
arrow->setStyle(endType);
|
||||
|
||||
arrow->setSize(balloon->EndTypeScale.getValue() * QGIArrow::getPrefArrowSize());
|
||||
arrow->draw();
|
||||
arrow->setPos(DU::toQPointF(arrowTipPosInParent));
|
||||
|
||||
Base::Vector3d arrowTipPos(arrowTipX, arrowTipY, 0.0);
|
||||
// arrowTip set above is unscaled, uninverted, unrotated and unRez'd.
|
||||
arrowTip = DGU::toGuiPoint(refObj, arrowTip);
|
||||
Base::Vector3d dirballoonLinesLine;
|
||||
if (!DrawUtil::fpCompare(kinkLength, 0.0)) {
|
||||
dirballoonLinesLine = (arrowTip - kinkPoint).Normalize();
|
||||
dirballoonLinesLine = (arrowTipPosInParent - kinkPoint).Normalize();
|
||||
}
|
||||
else {
|
||||
dirballoonLinesLine = (arrowTip - dLineStart).Normalize();
|
||||
dirballoonLinesLine = (arrowTipPosInParent - dLineStart).Normalize();
|
||||
}
|
||||
|
||||
float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI;
|
||||
|
||||
arrow->setPos(DU::toQPointF(arrowTip));
|
||||
if ((endType == ArrowType::FILLED_TRIANGLE) && (prefOrthoPyramid())) {
|
||||
if (arAngle < 0.0) {
|
||||
arAngle += 360.0;
|
||||
@@ -826,7 +833,7 @@ void QGIViewBalloon::drawBalloon(bool dragged)
|
||||
arrow->setRotation(arAngle);
|
||||
arrow->show();
|
||||
}
|
||||
dLinePath.lineTo(arrowTip.x - xAdj, arrowTip.y - yAdj);
|
||||
dLinePath.lineTo(arrowTipPosInParent.x - xAdj, arrowTipPosInParent.y - yAdj);
|
||||
balloonLines->setPath(dLinePath);
|
||||
|
||||
// This overwrites the previously created QPainterPath with empty one, in case it should be hidden. Should be refactored.
|
||||
@@ -967,4 +974,47 @@ DrawView* QGIViewBalloon::getSourceView() const
|
||||
return balloonParent;
|
||||
}
|
||||
|
||||
//! Calculate the required position of the arrow tip during drag operations. Uses the current
|
||||
//! label position and relative positions of the label and tip at the start of the drag.
|
||||
//! Note this returns the Gui position of the arrow, not the App position.
|
||||
Base::Vector3d QGIViewBalloon::arrowPosInDrag()
|
||||
{
|
||||
auto offsetGui = m_savePosition - m_saveOrigin;
|
||||
auto arrowPosGui = DU::toVector3d(balloonLabel->pos()) - offsetGui;
|
||||
return arrowPosGui;
|
||||
}
|
||||
|
||||
|
||||
//! retrieves the appropriate label position and origin (arrow) point
|
||||
void QGIViewBalloon::getBalloonPoints(TechDraw::DrawViewBalloon* balloon, DrawView *refObj,
|
||||
bool isDragging,
|
||||
Base::Vector3d& labelPos,
|
||||
Base::Vector3d& arrowPos)
|
||||
{
|
||||
float x, y;
|
||||
Base::Vector3d originApp{balloon->OriginX.getValue(), balloon->OriginY.getValue(), 0.0};
|
||||
Base::Vector3d arrowTipPosInParent;
|
||||
|
||||
// when not dragging take the X/Y properties otherwise the current label position
|
||||
if (!isDragging) {
|
||||
x = Rez::guiX(balloon->X.getValue() * refObj->getScale());
|
||||
y = Rez::guiX(balloon->Y.getValue() * refObj->getScale());
|
||||
arrowTipPosInParent = DGU::toGuiPoint(refObj, originApp);
|
||||
}
|
||||
else {
|
||||
x = balloonLabel->X();
|
||||
y = -balloonLabel->Y(); // invert from Qt scene units to R2 mm
|
||||
if (m_originDragged) {
|
||||
// moving the whole bubble object. do not adjust origin point.
|
||||
arrowTipPosInParent = arrowPosInDrag();
|
||||
} else {
|
||||
// this is a bubble drag, so the origin must remain in the same position on the view.
|
||||
// if the parent view is rotated, the origin scene position must be rotated to match
|
||||
arrowTipPosInParent = DGU::toGuiPoint(refObj, originApp);
|
||||
}
|
||||
}
|
||||
labelPos = Base::Vector3d(x, y, 0.0);
|
||||
arrowPos = arrowTipPosInParent;
|
||||
}
|
||||
|
||||
#include <Mod/TechDraw/Gui/moc_QGIViewBalloon.cpp>
|
||||
|
||||
@@ -78,6 +78,7 @@ public:
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
|
||||
QWidget* widget = nullptr) override;
|
||||
void setLabelCenter();
|
||||
Base::Vector3d getLabelCenter() const;
|
||||
void setPosFromCenter(const double& xCenter, const double& yCenter);
|
||||
double X() const
|
||||
{
|
||||
@@ -226,6 +227,13 @@ protected:
|
||||
QString getPrecision();
|
||||
void parentViewMousePressed(QGIView* view, QPointF pos);
|
||||
TechDraw::DrawView* getSourceView() const;
|
||||
Base::Vector3d arrowPosInDrag();
|
||||
void getBalloonPoints(TechDraw::DrawViewBalloon* balloon,
|
||||
TechDraw::DrawView* refObj,
|
||||
bool isDragging,
|
||||
Base::Vector3d& labelPos,
|
||||
Base::Vector3d& arrowPos);
|
||||
|
||||
|
||||
private:
|
||||
TechDraw::DrawViewBalloon* dvBalloon;
|
||||
@@ -241,7 +249,9 @@ private:
|
||||
bool m_dragInProgress;
|
||||
bool m_originDragged = false;
|
||||
bool m_ctrl;
|
||||
Base::Vector3d m_saveOffset;
|
||||
Base::Vector3d m_saveOriginOffset;
|
||||
Base::Vector3d m_saveOrigin;
|
||||
Base::Vector3d m_savePosition;
|
||||
};
|
||||
|
||||
}// namespace TechDrawGui
|
||||
|
||||
Reference in New Issue
Block a user