diff --git a/src/Mod/TechDraw/App/DrawViewDimension.cpp b/src/Mod/TechDraw/App/DrawViewDimension.cpp index 123a65eb38..d97f8293be 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.cpp +++ b/src/Mod/TechDraw/App/DrawViewDimension.cpp @@ -102,6 +102,8 @@ DrawViewDimension::DrawViewDimension(void) ADD_PROPERTY(Type,((long)0)); MeasureType.setEnums(MeasureTypeEnums); ADD_PROPERTY(MeasureType, ((long)1)); //Projected (or True) measurement + ADD_PROPERTY_TYPE(OverTolerance ,(0.0),"",App::Prop_None,"+ Tolerance value"); + ADD_PROPERTY_TYPE(UnderTolerance ,(0.0),"",App::Prop_None,"- Tolerance value"); //hide the properties the user can't edit in the property editor @@ -847,6 +849,18 @@ bool DrawViewDimension::has3DReferences(void) const return (References3D.getSize() > 0); } +bool DrawViewDimension::hasTolerance(void) const +{ + bool result = true; + double overTol = OverTolerance.getValue(); + double underTol = UnderTolerance.getValue(); + if (DrawUtil::fpCompare(overTol,0.0) && + DrawUtil::fpCompare(underTol,0.0) ) { + result = false; + } + return result; +} + bool DrawViewDimension::showUnits() const { bool result = false; diff --git a/src/Mod/TechDraw/App/DrawViewDimension.h b/src/Mod/TechDraw/App/DrawViewDimension.h index fe1db57de9..ccb00f13f7 100644 --- a/src/Mod/TechDraw/App/DrawViewDimension.h +++ b/src/Mod/TechDraw/App/DrawViewDimension.h @@ -99,10 +99,13 @@ public: App::PropertyEnumeration Type; //DistanceX,DistanceY,Diameter, etc App::PropertyString FormatSpec; App::PropertyBool Arbitrary; + App::PropertyFloat OverTolerance; + App::PropertyFloat UnderTolerance; short mustExecute() const; bool has2DReferences(void) const; bool has3DReferences(void) const; + bool hasTolerance(void) const; /** @name methods override Feature */ //@{ diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index f71ab6a0ad..6e1720d7f7 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -1073,7 +1073,7 @@ void MDIViewPage::setTreeToSceneSelect(void) QGIDatumLabel *dimLabel = dynamic_cast(*it); if(dimLabel) { - QGraphicsItem*dimParent = dimLabel->parentItem(); + QGraphicsItem*dimParent = dimLabel->QGraphicsItem::parentItem(); if(!dimParent) continue; diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index 75b0cf33db..b18eb25cb2 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,9 @@ #include "QGIDimLines.h" #include "QGIViewDimension.h" #include "ViewProviderDimension.h" +#include "DrawGuiUtil.h" + +//TODO: hide the Qt coord system (+y down). using namespace TechDraw; using namespace TechDrawGui; @@ -79,6 +83,11 @@ QGIDatumLabel::QGIDatumLabel() setFlag(ItemIsMovable, true); setFlag(ItemIsSelectable, true); setAcceptHoverEvents(true); + + m_dimText = new QGCustomText(); + m_dimText->setParentItem(this); + m_tolText = new QGCustomText(); + m_tolText->setParentItem(this); } QVariant QGIDatumLabel::itemChange(GraphicsItemChange change, const QVariant &value) @@ -97,26 +106,38 @@ QVariant QGIDatumLabel::itemChange(GraphicsItemChange change, const QVariant &va Q_EMIT dragging(); } - return QGCustomText::itemChange(change, value); + return QGraphicsItem::itemChange(change, value); } -void QGIDatumLabel::setPosFromCenter(const double &xCenter, const double &yCenter) +void QGIDatumLabel::mousePressEvent(QGraphicsSceneMouseEvent * event) { - //set label's Qt position(top,left) given boundingRect center point - setPos(xCenter - boundingRect().width() / 2., yCenter - boundingRect().height() / 2.); + if(scene() && this == scene()->mouseGrabberItem()) { + Q_EMIT dragFinished(); + } + QGraphicsItem::mousePressEvent(event); } -void QGIDatumLabel::setLabelCenter() +void QGIDatumLabel::mouseMoveEvent(QGraphicsSceneMouseEvent * event) { - //save label's bRect center (posX,posY) given Qt position (top,left) - posX = x() + boundingRect().width() / 2.; - posY = y() + boundingRect().height() / 2.; + QGraphicsItem::mouseMoveEvent(event); +} + +void QGIDatumLabel::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) +{ + if(scene() && this == scene()->mouseGrabberItem()) { + Q_EMIT dragFinished(); + } + + QGraphicsItem::mouseReleaseEvent(event); } void QGIDatumLabel::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { Q_EMIT hover(true); - QGCustomText::hoverEnterEvent(event); + if (!isSelected()) { + setPrettyPre(); + } + QGraphicsItem::hoverEnterEvent(event); } void QGIDatumLabel::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) @@ -125,20 +146,135 @@ void QGIDatumLabel::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) assert(view != 0); Q_EMIT hover(false); - if(!isSelected() && !view->isSelected()) { + if (!isSelected()) { setPrettyNormal(); } - QGraphicsTextItem::hoverLeaveEvent(event); + QGraphicsItem::hoverLeaveEvent(event); } -void QGIDatumLabel::mouseReleaseEvent( QGraphicsSceneMouseEvent * event) +QRectF QGIDatumLabel::boundingRect() const { - if(scene() && this == scene()->mouseGrabberItem()) { - Q_EMIT dragFinished(); - } - QGraphicsItem::mouseReleaseEvent(event); + return childrenBoundingRect(); } +void QGIDatumLabel::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + Q_UNUSED(painter); + QStyleOptionGraphicsItem myOption(*option); + myOption.state &= ~QStyle::State_Selected; + +// painter->drawRect(boundingRect()); //good for debugging + +} + +void QGIDatumLabel::setPosFromCenter(const double &xCenter, const double &yCenter) +{ + //set label's Qt position(top,left) given boundingRect center point + setPos(xCenter - m_dimText->boundingRect().width() / 2., yCenter - m_dimText->boundingRect().height() / 2.); + //set tolerance position + QRectF labelBox = m_dimText->boundingRect(); + double right = labelBox.right(); + double top = labelBox.top(); + m_tolText->setPos(right,top); +} + +void QGIDatumLabel::setLabelCenter() +{ + //save label's bRect center (posX,posY) given Qt position (top,left) + posX = x() + m_dimText->boundingRect().width() / 2.; + posY = y() + m_dimText->boundingRect().height() / 2.; +} + +void QGIDatumLabel::setFont(QFont f) +{ + m_dimText->setFont(f); + QFont tFont(f); + double fontSize = f.pointSizeF(); + double tolAdj = getTolAdjust(); + tFont.setPointSizeF(fontSize * tolAdj); + m_tolText->setFont(tFont); +} + +void QGIDatumLabel::setDimString(QString t) +{ + prepareGeometryChange(); + m_dimText->setPlainText(t); +} + +void QGIDatumLabel::setTolString() +{ + prepareGeometryChange(); + QGIViewDimension* qgivd = dynamic_cast(parentItem()); + if( qgivd == nullptr ) { + return; //tarfu + } + const auto dim( dynamic_cast(qgivd->getViewObject()) ); + if( dim == nullptr ) { + return; + } else if (!dim->hasTolerance()) { + return; + } + + double overTol = dim->OverTolerance.getValue(); + double underTol = dim->UnderTolerance.getValue(); + + int precision = getPrecision(); + QString overFormat = QString::number(overTol,'f', precision); + QString underFormat = QString::number(underTol,'f',precision); + + QString html = QString::fromUtf8("
%1
%2
"); + html = html.arg(overFormat).arg(underFormat); + m_tolText->setHtml(html); //<<< sometimes seg fault here in FT_Outline_Decompose () + //<<< only angle measures with degree symbol shown?? + + return; +} + +int QGIDatumLabel::getPrecision(void) +{ + int precision; + bool global = false; + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions"); + global = hGrp->GetBool("UseGlobalDecimals", true); + if (global) { + precision = Base::UnitsApi::getDecimals(); + } else { + precision = hGrp->GetInt("AltDecimals", 2); + } + return precision; +} + +double QGIDatumLabel::getTolAdjust(void) +{ + double adjust; + Base::Reference hGrp = App::GetApplication().GetUserParameter() + .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions"); + adjust = hGrp->GetFloat("TolSizeAdjust", 0.50); + return adjust; +} + + +void QGIDatumLabel::setPrettySel(void) +{ + m_dimText->setPrettySel(); + m_tolText->setPrettySel(); +} + +void QGIDatumLabel::setPrettyPre(void) +{ + m_dimText->setPrettyPre(); + m_tolText->setPrettyPre(); +} + +void QGIDatumLabel::setPrettyNormal(void) +{ + m_dimText->setPrettyNormal(); + m_tolText->setPrettyNormal(); +} + +//************************************************************** QGIViewDimension::QGIViewDimension() : hasHover(false), m_lineWidth(0.0) @@ -244,7 +380,7 @@ void QGIViewDimension::updateView(bool update) } else if(vp->Fontsize.isTouched() || vp->Font.isTouched()) { - QFont font = datumLabel->font(); + QFont font = datumLabel->getFont(); font.setPointSizeF(Rez::guiX(vp->Fontsize.getValue())); font.setFamily(QString::fromLatin1(vp->Font.getValue())); datumLabel->setFont(font); @@ -269,17 +405,29 @@ void QGIViewDimension::updateDim(bool obtuse) if ( vp == nullptr ) { return; } - - QString labelText = QString::fromUtf8(dim->getFormatedValue(obtuse).data(),dim->getFormatedValue().size()); - QFont font = datumLabel->font(); + + QString labelText = QString::fromUtf8(dim->getFormatedValue(obtuse).c_str()); + + QFont font = datumLabel->getFont(); font.setPointSizeF(Rez::guiX(vp->Fontsize.getValue())); font.setFamily(QString::fromUtf8(vp->Font.getValue())); datumLabel->setFont(font); prepareGeometryChange(); - datumLabel->setPlainText(labelText); + datumLabel->setDimString(labelText); + datumLabel->setTolString(); datumLabel->setPosFromCenter(datumLabel->X(),datumLabel->Y()); } +//this is for formatting and finding centers, not display +QString QGIViewDimension::getLabelText(void) +{ + QString result; + QString first = datumLabel->getDimText()->toPlainText(); + QString second = datumLabel->getTolText()->toPlainText(); + result = first + second; + return result; + +} void QGIViewDimension::datumLabelDragged() { @@ -336,8 +484,9 @@ void QGIViewDimension::draw() m_lineWidth = Rez::guiX(vp->LineWidth.getValue()); float margin = Rez::guiX(5.f); - QString labelText = datumLabel->toPlainText(); - Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0); //already gui coords +// QString labelText = datumLabel->toPlainText(); + QString labelText = getLabelText(); + Base::Vector3d lblCenter(datumLabel->X(), datumLabel->Y(), 0); //already Qt gui coords const char *dimType = dim->Type.getValueAsString(); @@ -352,7 +501,7 @@ void QGIViewDimension::draw() // +/- aligned method // dimension text legible from bottom or right - // text outside arrows (not between) + // text outside arrows (not between) iso convention (asme convention) // text to left of vertical dims // text above horizontal dims Base::Vector3d dirDist, normDist; //direction/normal vectors of distance line @@ -362,11 +511,11 @@ void QGIViewDimension::draw() dirDist = vecDist; dirDist.Normalize(); normDist = Base::Vector3d (-dirDist.y,dirDist.x, 0); //normal to distance direction - //toward dimension line? + //toward dimension line??? how to tell? if (strcmp(dimType, "Distance") == 0 ) { //distance and dimension lines parallel dirDim = dirDist; - normDim = Base::Vector3d (-dirDist.y,dirDist.x, 0); + normDim = normDist; } else if (strcmp(dimType, "DistanceX") == 0 ) { //distance and dimension lines not (necessarily) parallel dirDim = Base::Vector3d ( ((endDist.x - startDist.x >= FLT_EPSILON) ? 1 : -1) , 0, 0); @@ -378,7 +527,7 @@ void QGIViewDimension::draw() } //for ortho drawing extension lines are para to normDim, perp to dirDist - dirExt = normDim; + dirExt = normDim; //dirExt is para or anti-parallel to real extension direction dirIso = normDim; if (refObj->isIso()) { //is this dimension an iso dimension? ie points +/-isoX,+/-isoY,+/-isoZ @@ -388,65 +537,109 @@ void QGIViewDimension::draw() dirExt.Normalize(); // Get magnitude of angle between dimension line and horizontal - double angle = atan2(dirDim.y,dirDim.x); + // to determine rotation of dimension text (iso convention. asme is always upright) + //note qt y axis is reversed! and angles are CW! + double angle = atan2(-dirDim.y,dirDim.x); if (angle < 0.0) { angle = 2 * M_PI + angle; //map to +ve angle } //orient text right side up - bool isFlipped = false; - double angleFiddle = M_PI / 18.0; // 18 => 10*, 12 => 15*, ... - if ((angle > M_PI_2 - angleFiddle) && // > 80CW - (angle <= M_PI)) { // < 180CW +/-Q3 + double angleFiddle = M_PI / 10.0; // 18 => 10*, 12 => 15*, ... + if ((angle > M_PI_2 + angleFiddle) && // > 100CW + (angle <= M_PI)) { // < 180CW -> Q2 angle += M_PI; // flip CW - isFlipped = true; - } else if ((angle > M_PI) && // > 180CW +/-Q4 - (angle <= 1.5*M_PI - angleFiddle)) { // < 260CW + } else if ((angle > M_PI) && // > 180CW + (angle <= 1.5*M_PI - angleFiddle)) { // < 260CW -> Q3 angle -= M_PI; // flip CCW - isFlipped = true; } Base::Vector3d textNorm = normDim; - if (std::abs(dirDist.x) < FLT_EPSILON) { //this is DistanceY? - textNorm = Base::Vector3d(1.0,0.0,0.0); //force text to left of dim line - } else if (std::abs(dirDist.y) < FLT_EPSILON) { //this is DistanceX? - textNorm = Base::Vector3d(0.0,1.0,0.0); //force text above dim line - } else { - if (isFlipped) { - textNorm = -textNorm; - } + if (std::abs(dirDist.x) < FLT_EPSILON) { //this is DistanceY + textNorm = Base::Vector3d(-1.0,0.0,0.0); //text up is left (iso) + } else if (std::abs(dirDist.y) < FLT_EPSILON) { //this is DistanceX + textNorm = Base::Vector3d(0.0,1.0,0.0); //text up is up } - // +/- pos of startDist vs endDist for vert/horiz Dims // distStartDelta sb zero for normal dims float distStartDelta = vecDist.Dot(normDim); // component of distance vector in dim line direction Base::Vector3d startDistAdj = startDist + normDim * distStartDelta; - midDist = (startDistAdj + endDist) / 2.0; - //offset of dimLine from dimText + //offset of dimLine from getDimText() double offsetFudge = 2.0; - double textOffset = 1.0 * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge; + double textMult = 1.0; + if (dim->hasTolerance()) { + textMult = 1.5; + } + double textOffset = textMult * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge; - //fauxCenter is where the dimText would be if it was on the dimLine - Base::Vector3d fauxCenter = lblCenter + textOffset * textNorm; + QPointF qFigure = boundingRect().center(); + Base::Vector3d figureCenter(qFigure.x(),qFigure.y(),0.0); + + QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect()); + lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0); + + //find actual extension direction vector + Base::Vector3d startIntercept = DrawUtil::Intersect2d(startDist, dirExt, + lblCenter,dirDim); + Base::Vector3d dirExtActual = (startIntercept - startDist); + dirExtActual.Normalize(); + + midDist = (startDistAdj + endDist) / 2.0; //middle point of distance line + //fauxCenter is where the getDimText() would be if it was on the dimLine + Base::Vector3d fauxCenter; + if (strcmp(dimType, "Distance") == 0 ) { //oblique line + angle = -angle; + fauxCenter = lblCenter + textOffset * dirExtActual; + double slope; + if (DrawUtil::fpCompare(dirDist.x, 0.0)) { + slope = std::numeric_limits::max(); + } else { + slope = fabs(dirDist.y / dirDist.x); + } + if (slope > 1.0) { //mostly vertical + if (lblCenter.x > fauxCenter.x) { //label is to right of dimline + fauxCenter = lblCenter - textOffset*dirExtActual; //move dim line closer to figure + } + } else { //mostly horizontal + if (lblCenter.y > fauxCenter.y) { //label is below dimline + fauxCenter = lblCenter - textOffset*dirExtActual; //move dim line closer to figure + } + } + + } else if (strcmp(dimType, "DistanceX") == 0 ) { + if (lblCenter.y > figureCenter.y) { //text always above dimLine + fauxCenter = lblCenter + textOffset * textNorm; + } else { + fauxCenter = lblCenter + textOffset * textNorm; + } + } else if (strcmp(dimType, "DistanceY") == 0 ) { //text always to left of dimLine + angle = - angle; + if (lblCenter.x > figureCenter.x) { + fauxCenter = lblCenter - textOffset * textNorm; + } else { + fauxCenter = lblCenter - textOffset * textNorm; + } + } + + //intersection of extension lines and dimension line + startIntercept = DrawUtil::Intersect2d(startDist, dirExt, + fauxCenter,dirDim); + Base::Vector3d endIntercept = DrawUtil::Intersect2d(endDist, dirExt, + fauxCenter,dirDim); + + dirExtActual = (startIntercept - startDist); + dirExtActual.Normalize(); margin = Rez::guiX(2.f); float scaler = 1.; - //intersection of extension lines and dimension line - Base::Vector3d startIntercept = DrawUtil::Intersect2d(startDist, dirExt, - fauxCenter,dirDim); - Base::Vector3d endIntercept = DrawUtil::Intersect2d(endDist, dirExt, - fauxCenter,dirDim); - - Base::Vector3d dirExtActual = (startIntercept - startDist); - dirExtActual.Normalize(); Base::Vector3d extStartEnd = startIntercept + dirExtActual * (margin * scaler); Base::Vector3d extEndEnd = endIntercept + dirExtActual * (margin * scaler); //case 1: inner placement: text between extensions & fits. arros point out from inside (default) //case 2: inner placement2: text too big to fit. arrows point in from outside - //case 3: outer placement: text is outside extensions. arrows point in, 1 arrow tracks dimText + //case 3: outer placement: text is outside extensions. arrows point in, 1 arrow tracks getDimText() Base::Vector3d dim1Tip = startIntercept; Base::Vector3d dim1Tail = fauxCenter; @@ -504,8 +697,8 @@ void QGIViewDimension::draw() dimLines->setPath(path); // Note Bounding Box size is not the same width or height as text (only used for finding center) - float bbX = datumLabel->boundingRect().width(); - float bbY = datumLabel->boundingRect().height(); + double bbX = datumLabel->boundingRect().width(); + double bbY = datumLabel->boundingRect().height(); datumLabel->setTransformOriginPoint(bbX / 2, bbY /2); double angleOption = 0.0; //put lblText angle adjustments here datumLabel->setRotation((angle * 180 / M_PI) + angleOption); @@ -559,19 +752,25 @@ void QGIViewDimension::draw() arrow1Tail = curveCenter; arrow2Tail = curveCenter; - QFontMetrics fm(datumLabel->font()); - int textWidth = fm.width(labelText); - int charWidth = fm.width(QString::fromLatin1("M")); //full width character + double textWidth = datumLabel->getDimText()->boundingRect().width(); + if (dim->hasTolerance()) { + textWidth += datumLabel->getTolText()->boundingRect().width(); + } double gapMargin = Rez::guiX(4.f); margin = Rez::guiX(2.f); float scaler = 1.; double tip = (margin * scaler); double gap = (gapMargin * scaler); //sb % of radius? - //offset of dimLine from dimText + //offset of dimLine from getDimText() double offsetFudge = 2.0; - double vertOffset = 1.0 * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge; - double horizOffset = 1.0 * (textWidth/2.0) + (0.5 * charWidth) + offsetFudge; //a bit tight w/o more fudge + + double textMult = 1.0; + if (dim->hasTolerance()) { + textMult = 1.5; + } + double vertOffset = textMult * Rez::guiX(vp->Fontsize.getValue()) + offsetFudge; + double horizOffset = (textWidth/2.0) + offsetFudge; //a bit tight w/o more fudge bool outerPlacement = false; if ((lblCenter-curveCenter).Length() > radius) { //label is outside circle @@ -600,11 +799,14 @@ void QGIViewDimension::draw() posMode = VerticalSnap; } - fauxCenter = Base::Vector3d(lblCenter.x,lblCenter.y + vertOffset,lblCenter.z); +// fauxCenter = Base::Vector3d(lblCenter.x,lblCenter.y + vertOffset,lblCenter.z); if(posMode == VerticalSnap) { - if (lblCenter.y > curveCenter.y) { - //no op + QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect()); + lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0); + if (lblCenter.y > curveCenter.y) { // + fauxCenter = Base::Vector3d(lblCenter.x,lblCenter.y + vertOffset,lblCenter.z); } else { + fauxCenter = Base::Vector3d(lblCenter.x,lblCenter.y + vertOffset,lblCenter.z); tip = -tip; gap = -gap; } @@ -641,15 +843,20 @@ void QGIViewDimension::draw() path.moveTo(startExt2.x, startExt2.y); path.lineTo(endExt2.x, endExt2.y); - datumLabel->setRotation(0.); + datumLabel->setRotation(0.0); } else if(posMode == HorizontalSnap) { - if (lblCenter.x > curveCenter.x) { - fauxCenter = Base::Vector3d(lblCenter.x - horizOffset,lblCenter.y,lblCenter.z); - } else { + QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect()); + lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0); + + if (lblCenter.x > curveCenter.x) { //label right +// fauxCenter = Base::Vector3d(lblCenter.x - horizOffset,lblCenter.y,lblCenter.z); //unidirection convention + fauxCenter = Base::Vector3d(lblCenter.x + vertOffset,lblCenter.y,lblCenter.z); //aligned convention + } else { //label left tip = -tip; gap = -gap; - fauxCenter = Base::Vector3d(lblCenter.x + horizOffset,lblCenter.y,lblCenter.z); +// fauxCenter = Base::Vector3d(lblCenter.x + horizOffset,lblCenter.y,lblCenter.z); + fauxCenter = Base::Vector3d(lblCenter.x + vertOffset,lblCenter.y,lblCenter.z); } arrow1Tip.x = fauxCenter.x; @@ -684,9 +891,12 @@ void QGIViewDimension::draw() path.moveTo(startExt2.x, startExt2.y); path.lineTo(endExt2.x, endExt2.y); - datumLabel->setRotation(0.0); + datumLabel->setRotation(-90.0); //aligned convention +// datumLabel->setRotation(0.0); //unidirectional convention } else { //outer placement, NoSnap + QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect()); + lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0); isLeader = true; float spacer = (margin + textWidth / 2); spacer = (lblCenter.x < curveCenter.x) ? spacer : -spacer; @@ -838,9 +1048,8 @@ void QGIViewDimension::draw() radius = Rez::guiX(pts.radius); curveCenter = Rez::guiX(pts.center); pointOnCurve = Rez::guiX(pts.onCurve.first); - - QFontMetrics fm(datumLabel->font()); - int w = fm.width(labelText); + QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect()); + lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0); // Note Bounding Box size is not the same width or height as text (only used for finding center) float bbX = datumLabel->boundingRect().width(); @@ -849,7 +1058,7 @@ void QGIViewDimension::draw() datumLabel->setRotation(0.0); //label is always right side up & horizontal //if inside the arc (len(DimLine < radius)) arrow goes from center to edge away from label - //if inside the arc arrow kinks, then goes to edge nearest label + //if outside the arc arrow kinks, then goes to edge nearest label bool outerPlacement = false; if ((lblCenter - curveCenter).Length() > radius) { //label is outside circle outerPlacement = true; @@ -860,12 +1069,17 @@ void QGIViewDimension::draw() dirDimLine = Base::Vector3d(-1.0,0.0,0.0); } + double textWidth = datumLabel->getDimText()->boundingRect().width(); + if (dim->hasTolerance()) { + textWidth += datumLabel->getTolText()->boundingRect().width(); + } + Base::Vector3d dLineStart; Base::Vector3d kinkPoint; - margin = Rez::guiX(5.f); //space around label - double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)??? + margin = Rez::guiX(5.f); //space around label + double kinkLength = Rez::guiX(5.0); //sb % of horizontal dist(lblCenter,curveCenter)??? if (outerPlacement) { - float offset = (margin + w / 2); + double offset = (margin + textWidth / 2.0); offset = (lblCenter.x < curveCenter.x) ? offset : -offset; //if label on left then tip is +ve (ie to right) dLineStart.y = lblCenter.y; dLineStart.x = lblCenter.x + offset; //start at right or left of label @@ -971,14 +1185,21 @@ void QGIViewDimension::draw() ccwInner = false; } - Base::Vector3d labelVec = (lblCenter - vertex); //dir from label to vertex - QFontMetrics fm(datumLabel->font()); - int h = fm.height(); - double radius = labelVec.Length(); - radius -= h * 0.6; // Adjust the radius so the label isn't over the line + QRectF mappedRect = mapRectFromItem(datumLabel, datumLabel->boundingRect()); + lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0); - double labelangle = atan2(-labelVec.y, labelVec.x); //angle with +X axis on [-PI,+PI] - if (labelangle < 0) { //map to [0,2PI) + Base::Vector3d labelVec = (lblCenter - vertex); //dir from label to vertex + + double textHeight = datumLabel->getDimText()->boundingRect().height(); + if (dim->hasTolerance()) { + textHeight = datumLabel->getTolText()->boundingRect().height(); + } + double offsetFudge = 2.0; + double textOffset = textHeight/2.0 + offsetFudge; + double radius = labelVec.Length() - textOffset; + + double labelangle = atan2(-labelVec.y, labelVec.x); //angle with +X axis on [-PI,+PI] (iso) + if (labelangle < 0) { //map to [0,2PI) (asme angle = 0.0) labelangle += 2.0 * M_PI; } @@ -998,7 +1219,7 @@ void QGIViewDimension::draw() Base::Vector3d startExt0 = legEnd0; Base::Vector3d startExt1 = legEnd1; // add an offset from the ends - double offsetFudge = 5.0; + offsetFudge = 5.0; startExt0 += d0 * offsetFudge; startExt1 += d1 * offsetFudge; diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.h b/src/Mod/TechDraw/Gui/QGIViewDimension.h index 9b77efb286..3e7e840fef 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.h +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.h @@ -26,9 +26,10 @@ #include #include #include -#include -#include +#include +#include #include +#include #include #include "QGIView.h" #include "QGCustomText.h" @@ -46,22 +47,41 @@ namespace TechDrawGui { class QGIArrow; class QGIDimLines; +class QGIViewDimension; -class QGIDatumLabel : public QGCustomText +class QGIDatumLabel : public QGraphicsObject { Q_OBJECT public: - explicit QGIDatumLabel(); - ~QGIDatumLabel() {} + QGIDatumLabel(); + virtual ~QGIDatumLabel() = default; enum {Type = QGraphicsItem::UserType + 107}; int type() const { return Type;} + virtual QRectF boundingRect() const override; + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + virtual void paint( QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget = nullptr ) override; void setLabelCenter(); void setPosFromCenter(const double &xCenter, const double &yCenter); double X() const { return posX; } - double Y() const { return posY; } + double Y() const { return posY; } //minus posY? + + void setFont(QFont f); + QFont getFont(void) { return m_dimText->font(); } + void setDimString(QString t); + void setTolString(); + void setPrettySel(void); + void setPrettyPre(void); + void setPrettyNormal(void); + + QGCustomText* getDimText(void) { return m_dimText; } + void setDimText(QGCustomText* newText) { m_dimText = newText; } + QGCustomText* getTolText(void) { return m_tolText; } + void setTolText(QGCustomText* newTol) { m_tolText = newTol; } Q_SIGNALS: void dragging(); @@ -70,12 +90,17 @@ Q_SIGNALS: void dragFinished(); protected: - // Preselection events: - void mouseReleaseEvent( QGraphicsSceneMouseEvent * event); - virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); - // Selection detection - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override; + virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; + virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; +// virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent * event) override; + + QGCustomText* m_dimText; + QGCustomText* m_tolText; + int getPrecision(void); + double getTolAdjust(void); double posX; double posY; @@ -83,6 +108,8 @@ protected: private: }; +//******************************************************************* + class TechDrawGuiExport QGIViewDimension : public QObject, public QGIView { Q_OBJECT @@ -102,6 +129,7 @@ public: const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ) override; virtual QColor getNormalColor(void) override; + QString getLabelText(void); public Q_SLOTS: void datumLabelDragged(void); @@ -118,6 +146,7 @@ protected: virtual void setPens(void); Base::Vector3d findIsoDir(Base::Vector3d ortho); Base::Vector3d findIsoExt(Base::Vector3d isoDir); + QString getPrecision(void); protected: bool hasHover;