Download src/Mod/TechDraw/Gui/CommandCreateDims.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 91.3 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/TechDraw/Gui/CommandCreateDims.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/TechDraw/Gui/CommandCreateDims.cpp
-
curl -L -o CommandCreateDims.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/TechDraw/Gui/CommandCreateDims.cpp
91.3 kB
| /*************************************************************************** | |
| * Copyright (c) 2014 Luke Parry <l.parry@warwick.ac.uk> * | |
| * Copyright (c) 2022 WandererFan <wandererfan@gmail.com> * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This library is free software; you can redistribute it and/or * | |
| * modify it under the terms of the GNU Library General Public * | |
| * License as published by the Free Software Foundation; either * | |
| * version 2 of the License, or (at your option) any later version. * | |
| * * | |
| * This library 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 Library General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Library General Public * | |
| * License along with this library; see the file COPYING.LIB. If not, * | |
| * write to the Free Software Foundation, Inc., 59 Temple Place, * | |
| * Suite 330, Boston, MA 02111-1307, USA * | |
| * * | |
| ***************************************************************************/ | |
| using namespace TechDrawGui; | |
| using namespace TechDraw; | |
| using namespace std; | |
| using DimensionType = TechDraw::DrawViewDimension::DimensionType; | |
| using DimensionGeometry = TechDraw::DimensionGeometry; | |
| //=========================================================================== | |
| // utility routines | |
| //=========================================================================== | |
| //internal functions | |
| bool _checkSelection(Gui::Command* cmd, unsigned maxObjs = 2); | |
| bool _checkDrawViewPart(Gui::Command* cmd); | |
| bool isDimCmdActive(Gui::Command* cmd) | |
| { | |
| bool havePage = DrawGuiUtil::needPage(cmd); | |
| bool haveView = DrawGuiUtil::needView(cmd); | |
| return (havePage && haveView); | |
| } | |
| void execDistance(Gui::Command* cmd); | |
| void execDistanceX(Gui::Command* cmd); | |
| void execDistanceY(Gui::Command* cmd); | |
| void execAngle(Gui::Command* cmd); | |
| void execAngle3Pt(Gui::Command* cmd); | |
| void execRadius(Gui::Command* cmd); | |
| void execDiameter(Gui::Command* cmd); | |
| void execArea(Gui::Command* cmd); | |
| void execDim(Gui::Command* cmd, std::string type, StringVector acceptableGeometry, std::vector<int> minimumCounts, std::vector<DimensionGeometry> acceptableDimensionGeometrys); | |
| void execExtent(Gui::Command* cmd, const std::string& dimType); | |
| DrawViewDimension* dimensionMaker(TechDraw::DrawViewPart* dvp, std::string dimType, | |
| ReferenceVector references2d, ReferenceVector references3d); | |
| DrawViewDimension* dimMaker(TechDraw::DrawViewPart* dvp, std::string dimType, | |
| ReferenceVector references2d, ReferenceVector references3d); | |
| void positionDimText(DrawViewDimension* dim, int indexOffset = 0); | |
| void activateHandler(TechDrawHandler* newHandler) | |
| { | |
| std::unique_ptr<TechDrawHandler> ptr(newHandler); | |
| auto* mdi = qobject_cast<MDIViewPage*>(Gui::getMainWindow()->activeWindow()); | |
| if (!mdi) { | |
| return; | |
| } | |
| ViewProviderPage* vp = mdi->getViewProviderPage(); | |
| if (!vp) { | |
| return; | |
| } | |
| QGVPage* viewPage = vp->getQGVPage(); | |
| if (!viewPage) { | |
| return; | |
| } | |
| viewPage->activateHandler(ptr.release()); | |
| } | |
| //=========================================================================== | |
| // TechDraw_Dimension | |
| //=========================================================================== | |
| class GeomSelectionSizes | |
| { | |
| public: | |
| GeomSelectionSizes(size_t s_pts, size_t s_lns, size_t s_cir, size_t s_ell, size_t s_spl, size_t s_fcs) : | |
| s_pts(s_pts), s_lns(s_lns), s_cir(s_cir), s_ell(s_ell), s_spl(s_spl), s_fcs(s_fcs) {} | |
| ~GeomSelectionSizes() {} | |
| bool hasPoints() const { return s_pts > 0; } | |
| bool hasLines() const { return s_lns > 0; } | |
| bool hasCirclesOrArcs() const { return s_cir > 0; } | |
| bool hasEllipseAndCo() const { return s_ell > 0; } | |
| bool hasSplineAndCo() const { return s_spl > 0; } | |
| bool hasFaces() const { return s_fcs > 0; } | |
| bool has1Face() const { return s_pts == 0 && s_lns == 0 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 1; } | |
| bool has1Point() const { return s_pts == 1 && s_lns == 0 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has2Points() const { return s_pts == 2 && s_lns == 0 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Point1Line() const { return s_pts == 1 && s_lns == 1 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has3Points() const { return s_pts == 3 && s_lns == 0 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has4MorePoints() const { return s_pts >= 4 && s_lns == 0 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has2Points1Line() const { return s_pts == 2 && s_lns == 1 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has3MorePoints1Line() const { return s_pts >= 3 && s_lns == 1 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Point1Circle() const { return s_pts == 1 && s_lns == 0 && s_cir == 1 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Point1Ellipse() const { return s_pts == 1 && s_lns == 0 && s_cir == 0 && s_ell == 1 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Line() const { return s_pts == 0 && s_lns == 1 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has2Lines() const { return s_pts == 0 && s_lns == 2 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has3MoreLines() const { return s_pts == 0 && s_lns >= 3 && s_cir == 0 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Line1Circle() const { return s_pts == 0 && s_lns == 1 && s_cir == 1 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Line2Circles() const { return s_pts == 0 && s_lns == 1 && s_cir == 2 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Line1Ellipse() const { return s_pts == 0 && s_lns == 1 && s_cir == 0 && s_ell == 1 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Circle() const { return s_pts == 0 && s_lns == 0 && s_cir == 1 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has2Circles() const { return s_pts == 0 && s_lns == 0 && s_cir == 2 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has3MoreCircles() const { return s_pts == 0 && s_lns == 0 && s_cir >= 3 && s_ell == 0 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Circle1Ellipse() const { return s_pts == 0 && s_lns == 0 && s_cir == 1 && s_ell == 1 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Ellipse() const { return s_pts == 0 && s_lns == 0 && s_cir == 0 && s_ell == 1 && s_spl == 0 && s_fcs == 0; } | |
| bool has2Ellipses() const { return s_pts == 0 && s_lns == 0 && s_cir == 0 && s_ell == 2 && s_spl == 0 && s_fcs == 0; } | |
| bool has1Spline() const { return s_pts == 0 && s_lns == 0 && s_cir == 0 && s_ell == 0 && s_spl == 1 && s_fcs == 0; } | |
| bool has1SplineAndMore() const { return s_spl >= 1 && s_fcs == 0; } | |
| size_t s_pts, s_lns, s_cir, s_ell, s_spl, s_fcs; | |
| }; | |
| class TDHandlerDimension : public TechDrawHandler, | |
| public Gui::SelectionObserver | |
| { | |
| public: | |
| explicit TDHandlerDimension(ReferenceVector refs, TechDraw::DrawViewPart* pFeat) | |
| : SelectionObserver(true) | |
| , specialDimension(SpecialDimension::None) | |
| , availableDimension(AvailableDimension::FIRST) | |
| , mousePos(QPoint(0, 0)) | |
| , selPoints({}) | |
| , selLine({}) | |
| , selCircleArc({}) | |
| , selEllipseArc({}) | |
| , selSplineAndCo({}) | |
| , selFaces({}) | |
| , emptyVector({}) | |
| , addedRef(ReferenceEntry()) | |
| , removedRef(ReferenceEntry()) | |
| , initialSelection(std::move(refs)) | |
| , partFeat(pFeat) | |
| , dims({}) | |
| , blockRemoveSel(false) | |
| { | |
| } | |
| ~TDHandlerDimension() | |
| { | |
| } | |
| enum class AvailableDimension { | |
| FIRST, | |
| SECOND, | |
| THIRD, | |
| FOURTH, | |
| FIFTH, | |
| RESET | |
| }; | |
| enum class SpecialDimension { | |
| LineOr2PointsDistance, | |
| LineOr2PointsChamfer, | |
| ExtendDistance, | |
| ChainDistance, | |
| CoordDistance, | |
| None | |
| }; | |
| void activated() override | |
| { | |
| auto* mdi = qobject_cast<MDIViewPage*>(Gui::getMainWindow()->activeWindow()); | |
| if (mdi) { | |
| mdi->setDimensionsSelectability(false); | |
| } | |
| Gui::Selection().setSelectionStyle(Gui::SelectionSingleton::SelectionStyle::GreedySelection); | |
| Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Insert dimension")); | |
| handleInitialSelection(); | |
| } | |
| void deactivated() override | |
| { | |
| auto* mdi = qobject_cast<MDIViewPage*>(Gui::getMainWindow()->activeWindow()); | |
| if (mdi) { | |
| mdi->setDimensionsSelectability(true); | |
| } | |
| Gui::Selection().setSelectionStyle(Gui::SelectionSingleton::SelectionStyle::NormalSelection); | |
| Gui::Command::abortCommand(); | |
| } | |
| void keyPressEvent(QKeyEvent* event) override | |
| { | |
| if (event->key() == Qt::Key_M && !selectionEmpty()) { | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| availableDimension = AvailableDimension::SECOND; | |
| } | |
| else if (availableDimension == AvailableDimension::SECOND) { | |
| availableDimension = AvailableDimension::THIRD; | |
| } | |
| else if (availableDimension == AvailableDimension::THIRD) { | |
| availableDimension = AvailableDimension::FOURTH; | |
| } | |
| else if (availableDimension == AvailableDimension::FOURTH) { | |
| availableDimension = AvailableDimension::FIFTH; | |
| } | |
| else if (availableDimension == AvailableDimension::FIFTH || availableDimension == AvailableDimension::RESET) { | |
| availableDimension = AvailableDimension::FIRST; | |
| } | |
| makeAppropriateDimension(); | |
| event->accept(); | |
| } | |
| else if (event->key() == Qt::Key_Z && (QApplication::keyboardModifiers() & Qt::ControlModifier)) { | |
| // User trying to cancel with Ctrl-Z | |
| quit(); | |
| event->accept(); | |
| } | |
| } | |
| void keyReleaseEvent(QKeyEvent* event) override | |
| { | |
| if (event->key() == Qt::Key_Z && (QApplication::keyboardModifiers() & Qt::ControlModifier)) { | |
| // User trying to cancel with Ctrl-Z | |
| quit(); | |
| event->accept(); | |
| } | |
| else { | |
| TechDrawHandler::keyReleaseEvent(event); | |
| } | |
| } | |
| void mouseMoveEvent(QMouseEvent* event) override | |
| { | |
| mousePos = event->pos(); | |
| if (dims.empty()){ | |
| return; | |
| } | |
| bool textToMiddle = false; | |
| Base::Vector3d dirMaster, delta; | |
| //Change distance dimension based on position of mouse. | |
| if (specialDimension == SpecialDimension::LineOr2PointsDistance | |
| || specialDimension == SpecialDimension::LineOr2PointsChamfer){ | |
| updateDistanceType(); | |
| } | |
| else if (specialDimension == SpecialDimension::ExtendDistance){ | |
| updateExtentDistanceType(); | |
| } | |
| else if (specialDimension == SpecialDimension::ChainDistance || specialDimension == SpecialDimension::CoordDistance){ | |
| updateChainDistanceType(); | |
| textToMiddle = true; | |
| pointPair pp = dims[0]->getLinearPoints(); | |
| dirMaster = pp.second() - pp.first(); | |
| //dirMaster.y = -dirMaster.y; // not needed because y is reversed between property X/Y and scenePositions | |
| QPointF firstPos = getDimLabel(dims[0])->pos(); | |
| Base::Vector3d pMaster(firstPos.x(), firstPos.y(), 0.0); | |
| Base::Vector3d ipDelta = DrawUtil::getTrianglePoint(pMaster, dirMaster, Base::Vector3d()); | |
| delta = ipDelta.Normalize() * Rez::guiX(activeDimAttributes.getCascadeSpacing()); | |
| } | |
| int i = 0; | |
| for (auto* dim : dims) { | |
| auto dimType = static_cast<DimensionType>(dim->Type.getValue()); | |
| moveDimension(mousePos, dim, textToMiddle, dirMaster, delta, dimType, i); | |
| if (specialDimension == SpecialDimension::CoordDistance) { | |
| i++; | |
| } | |
| } | |
| } | |
| QGIDatumLabel* getDimLabel(DrawViewDimension* d) | |
| { | |
| auto* vp = freecad_cast<ViewProviderDimension*>(Gui::Application::Instance->getViewProvider(d)); | |
| if (!vp) { | |
| return nullptr; | |
| } | |
| auto* qgivDimension(dynamic_cast<QGIViewDimension*>(vp->getQView())); | |
| if (!qgivDimension) { | |
| return nullptr; | |
| } | |
| return qgivDimension->getDatumLabel(); | |
| } | |
| void moveDimension(QPoint pos, DrawViewDimension* dim, bool textToMiddle = false, Base::Vector3d dir = Base::Vector3d(), | |
| Base::Vector3d delta = Base::Vector3d(), DimensionType type = DimensionType::Distance, int i = 0) | |
| { | |
| if (!dim) { return; } | |
| auto label = getDimLabel(dim); | |
| if (!label) { return; } | |
| label->setPos(getDimPositionToBe(pos, label->pos(), textToMiddle, dir, delta, type, i)); | |
| } | |
| QPointF getDimPositionToBe(QPoint pos, QPointF curPos = QPointF(), bool textToMiddle = false, Base::Vector3d dir = Base::Vector3d(), | |
| Base::Vector3d delta = Base::Vector3d(), DimensionType type = DimensionType::Distance, int i = 0) | |
| { | |
| auto* vpp = freecad_cast<ViewProviderDrawingView*>(Gui::Application::Instance->getViewProvider(partFeat)); | |
| if (!vpp) { return QPointF(); } | |
| QPointF scenePos = viewPage->mapToScene(pos) - vpp->getQView()->scenePos(); | |
| if (textToMiddle) { | |
| // delta is for coord distances. i = 0 when it's a chain so delta is ignored. | |
| float dimDistance = Rez::guiX(activeDimAttributes.getCascadeSpacing()); | |
| if (type == DimensionType::Distance) { | |
| Base::Vector3d pos3d(scenePos.x(), scenePos.y(), 0.0); | |
| float xDim = curPos.x(); | |
| float yDim = curPos.y(); | |
| Base::Vector3d pDim(xDim, yDim, 0.0); | |
| Base::Vector3d p3 = DrawUtil::getTrianglePoint(pos3d, dir, pDim); | |
| p3 = p3 + delta * i; | |
| scenePos = QPointF(p3.x, p3.y); | |
| } | |
| else if(type == DimensionType::DistanceX) { | |
| pointPair pp = dims[0]->getLinearPoints(); | |
| if (Rez::guiX(pp.first().y) > scenePos.y()) | |
| dimDistance = -dimDistance; | |
| double y = static_cast<double>(scenePos.y()) + i * static_cast<double>(dimDistance); | |
| scenePos = QPointF(curPos.x(), y); | |
| } | |
| else if(type == DimensionType::DistanceY) { | |
| pointPair pp = dims[0]->getLinearPoints(); | |
| if (Rez::guiX(pp.first().x) > scenePos.x()) | |
| dimDistance = -dimDistance; | |
| double x = static_cast<double>(scenePos.x()) + i * static_cast<double>(dimDistance); | |
| scenePos = QPointF(x, curPos.y()); | |
| } | |
| } | |
| return scenePos; | |
| } | |
| void finishDimensionMove() | |
| { | |
| for (auto* dim : dims) { | |
| auto label = getDimLabel(dim); | |
| double x = Rez::appX(label->X()), y = Rez::appX(label->Y()); | |
| Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.X = %f", | |
| dim->getNameInDocument(), x); | |
| Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Y = %f", | |
| dim->getNameInDocument(), -y); | |
| } | |
| } | |
| void setDimsSelectability(bool val) | |
| { | |
| for (auto dim : dims) { | |
| setDimSelectability(dim, val); | |
| } | |
| } | |
| void setDimSelectability(DrawViewDimension* d, bool val) | |
| { | |
| QGIDatumLabel* label = getDimLabel(d); | |
| if (label) { | |
| label->setSelectability(val); | |
| } | |
| } | |
| void mouseReleaseEvent(QMouseEvent* event) override | |
| { | |
| if (event->button() == Qt::RightButton) { | |
| if (!dims.empty()) { | |
| Gui::Selection().clearSelection(); | |
| clearAndRestartCommand(); | |
| event->accept(); | |
| } | |
| else { | |
| TechDrawHandler::mouseReleaseEvent(event); | |
| } | |
| return; | |
| } | |
| else if (event->button() == Qt::LeftButton) { | |
| mousePos = event->pos(); | |
| bool finalize = true; | |
| if (removedRef.hasGeometry()) { | |
| finalize = false; | |
| ReferenceVector& selVector = getSelectionVector(removedRef); | |
| selVector.erase(std::remove(selVector.begin(), selVector.end(), removedRef), selVector.end()); | |
| if (!selectionEmpty()) { | |
| availableDimension = AvailableDimension::FIRST; | |
| makeAppropriateDimension(); | |
| } | |
| else { | |
| clearAndRestartCommand(); | |
| } | |
| removedRef = ReferenceEntry(); | |
| } | |
| if (addedRef.hasGeometry()) { | |
| finalize = false; | |
| //add the geometry to its type vector. Temporarily if not selAllowed | |
| if (addedRef.getSubName() == "") { | |
| // Behavior deactivated for now because I found it annoying. | |
| // To reactivate replace addedRef.hasGeometry() by addedRef.getObject() above. | |
| // This means user selected the view itself. | |
| if (selectionEmpty()) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| } | |
| } | |
| else { | |
| ReferenceVector& selVector = getSelectionVector(addedRef); | |
| selVector.push_back(addedRef); | |
| availableDimension = AvailableDimension::FIRST; | |
| bool selAllowed = makeAppropriateDimension(); | |
| if (!selAllowed) { | |
| // remove from selection | |
| blockRemoveSel = true; | |
| Gui::Selection().rmvSelection(addedRef.getObject()->getDocument()->getName(), | |
| addedRef.getObject()->getNameInDocument(), addedRef.getSubName().c_str()); | |
| blockRemoveSel = false; | |
| if (selVector == selFaces) { | |
| // if sel face and not allowed, then a dimension is being created | |
| // and user clicked on a face to drop it. | |
| // Better would be to disable face selectability when needed. | |
| finalize = true; | |
| } | |
| } | |
| } | |
| addedRef = ReferenceEntry(); | |
| } | |
| // Finalize if click on empty space. | |
| if (finalize && !dims.empty()) { | |
| finalizeCommand(); | |
| } | |
| } | |
| } | |
| void onSelectionChanged(const Gui::SelectionChanges& msg) override | |
| { | |
| if (msg.Type == Gui::SelectionChanges::ClrSelection) { | |
| return; | |
| } | |
| App::Document* pageDoc = nullptr; | |
| if (auto page = getPage()) { | |
| pageDoc = page->getDocument(); | |
| } | |
| if (msg.Object.getObjectName().empty() | |
| || (msg.Object.getDocument() != pageDoc)) { | |
| if (msg.Type == Gui::SelectionChanges::AddSelection) { | |
| Gui::Selection().rmvSelection(msg.pDocName, msg.pObjectName, msg.pSubName); | |
| } | |
| return; | |
| } | |
| App::DocumentObject* obj = msg.Object.getObject(); | |
| if (!obj) { | |
| if (msg.Type == Gui::SelectionChanges::AddSelection) { | |
| Gui::Selection().rmvSelection(msg.pDocName, msg.pObjectName, msg.pSubName); | |
| } | |
| return; | |
| } | |
| auto* dvp = dynamic_cast<TechDraw::DrawViewPart*>(obj); | |
| if (!dvp) { | |
| if (msg.Type == Gui::SelectionChanges::AddSelection) { | |
| Gui::Selection().rmvSelection(msg.pDocName, msg.pObjectName, msg.pSubName); | |
| } | |
| return; | |
| } | |
| if (partFeat && partFeat != dvp) { | |
| // Dimensions can only be within one view. | |
| if (msg.Type == Gui::SelectionChanges::AddSelection) { | |
| Gui::Selection().rmvSelection(msg.pDocName, msg.pObjectName, msg.pSubName); | |
| } | |
| return; | |
| } | |
| else { | |
| partFeat = dvp; | |
| } | |
| if (msg.Type == Gui::SelectionChanges::AddSelection) { | |
| addedRef = ReferenceEntry(dvp, msg.pSubName); | |
| } | |
| else if (msg.Type == Gui::SelectionChanges::RmvSelection) { | |
| if (!blockRemoveSel) { | |
| removedRef = ReferenceEntry(dvp, msg.pSubName); | |
| } | |
| } | |
| } | |
| private: | |
| QString getCrosshairCursorSVGName() const override | |
| { | |
| return QStringLiteral("TechDraw_Dimension_Pointer"); | |
| } | |
| protected: | |
| SpecialDimension specialDimension; | |
| AvailableDimension availableDimension; | |
| QPoint mousePos; | |
| ReferenceVector selPoints; | |
| ReferenceVector selLine; | |
| ReferenceVector selCircleArc; | |
| ReferenceVector selEllipseArc; | |
| ReferenceVector selSplineAndCo; | |
| ReferenceVector selFaces; | |
| ReferenceVector emptyVector; | |
| ReferenceEntry addedRef; | |
| ReferenceEntry removedRef; | |
| ReferenceVector initialSelection; | |
| TechDraw::DrawViewPart* partFeat; | |
| std::vector<DrawViewDimension*> dims; | |
| bool blockRemoveSel; | |
| void handleInitialSelection() | |
| { | |
| if (initialSelection.size() == 0) { | |
| return; | |
| } | |
| availableDimension = AvailableDimension::FIRST; | |
| partFeat = dynamic_cast<TechDraw::DrawViewPart*>(initialSelection[0].getObject()); | |
| if (!partFeat) { return; } | |
| // Add the selected elements to their corresponding selection vectors | |
| for (auto& ref : initialSelection) { | |
| ReferenceVector& selVector = getSelectionVector(ref); | |
| selVector.push_back(ref); | |
| } | |
| // See if the selection is valid | |
| bool selAllowed = makeAppropriateDimension(); | |
| if (!selAllowed) { | |
| clearRefVectors(); | |
| } | |
| } | |
| void finalizeCommand() | |
| { | |
| finishDimensionMove(); | |
| // Ask for the value of datum dimensions | |
| ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/TechDraw"); | |
| Gui::Command::commitCommand(); | |
| // Touch the parent feature so the dimension in tree view appears as a child | |
| partFeat->touch(true); | |
| // This code enables the continuous creation mode. | |
| bool continuousMode = hGrp->GetBool("ContinuousCreationMode", true); | |
| if (continuousMode) { | |
| Gui::Selection().clearSelection(); | |
| clearAndRestartCommand(); | |
| } | |
| else { | |
| viewPage->deactivateHandler(); // no code after this line, Handler get deleted in QGVPage | |
| } | |
| } | |
| ReferenceVector& getSelectionVector(ReferenceEntry& ref) | |
| { | |
| std::string subName = ref.getSubName(); | |
| if (subName == "") { | |
| return emptyVector; | |
| } | |
| auto* dvp = static_cast<TechDraw::DrawViewPart*>(ref.getObject()); | |
| std::string geomName = DrawUtil::getGeomTypeFromName(subName); | |
| if (geomName == "Face") { | |
| return selFaces; | |
| } | |
| else if (geomName == "Edge") { | |
| int GeoId(TechDraw::DrawUtil::getIndexFromName(subName)); | |
| TechDraw::BaseGeomPtr geom = dvp->getGeomByIndex(GeoId); | |
| if (!geom) { | |
| return emptyVector; | |
| } | |
| if (geom->getGeomType() == GeomType::GENERIC) { | |
| TechDraw::GenericPtr gen1 = std::static_pointer_cast<TechDraw::Generic>(geom); | |
| if (gen1->points.size() < 2) { | |
| return emptyVector; | |
| } | |
| return selLine; | |
| } | |
| else if (geom->getGeomType() == GeomType::CIRCLE || geom->getGeomType() == GeomType::ARCOFCIRCLE) { | |
| return selCircleArc; | |
| } | |
| else if (geom->getGeomType() == GeomType::ELLIPSE || geom->getGeomType() == GeomType::ARCOFELLIPSE) { | |
| return selEllipseArc; | |
| } | |
| else if (geom->getGeomType() == GeomType::BSPLINE) { | |
| return selSplineAndCo; | |
| } | |
| } | |
| else if (geomName == "Vertex") { | |
| return selPoints; | |
| } | |
| return emptyVector; | |
| } | |
| bool selectionEmpty() | |
| { | |
| return selPoints.empty() && selLine.empty() && selCircleArc.empty() && selEllipseArc.empty() && selSplineAndCo.empty() && selFaces.empty(); | |
| } | |
| ReferenceVector allRefs() | |
| { | |
| ReferenceVector result; | |
| result.reserve(selPoints.size() + selLine.size() + selCircleArc.size() + selEllipseArc.size() + selSplineAndCo.size() + selFaces.size()); | |
| // Append each vector to result | |
| result.insert(result.end(), selPoints.begin(), selPoints.end()); | |
| result.insert(result.end(), selLine.begin(), selLine.end()); | |
| result.insert(result.end(), selCircleArc.begin(), selCircleArc.end()); | |
| result.insert(result.end(), selEllipseArc.begin(), selEllipseArc.end()); | |
| result.insert(result.end(), selSplineAndCo.begin(), selSplineAndCo.end()); | |
| result.insert(result.end(), selFaces.begin(), selFaces.end()); | |
| return result; | |
| } | |
| bool makeAppropriateDimension() { | |
| bool selAllowed = false; | |
| GeomSelectionSizes selection(selPoints.size(), selLine.size(), selCircleArc.size(), selEllipseArc.size(), selSplineAndCo.size(), selFaces.size()); | |
| if (selection.hasFaces()) { | |
| makeCts_Faces(selAllowed); | |
| if (!selection.has1Face()) { | |
| Base::Console().warning("Multiple faces are selected. Using first.\n"); | |
| } | |
| } | |
| else if (selection.hasPoints()) { | |
| if (selection.has1Point()) { selAllowed = true; } | |
| else if (selection.has2Points()) { makeCts_2Point(selAllowed); } | |
| else if (selection.has3Points()) { makeCts_3Point(selAllowed); } | |
| else if (selection.has4MorePoints()) { makeCts_4MorePoints(selAllowed); } | |
| else if (selection.has1Point1Line()) { makeCts_1Point1Line(selAllowed); } | |
| else if (selection.has1Point1Circle()) { makeCts_1Point1Circle(selAllowed); } | |
| else if (selection.has1Point1Ellipse()) { makeCts_1Point1Ellipse(selAllowed); } | |
| } | |
| else if (selection.hasLines()) { | |
| if (selection.has1Line()) { makeCts_1Line(selAllowed); } | |
| else if (selection.has2Lines()) { makeCts_2Line(selAllowed); } | |
| else if (selection.has1Line1Circle()) { makeCts_1Line1Circle(selAllowed); } | |
| else if (selection.has1Line1Ellipse()) { makeCts_1Line1Ellipse(selAllowed); } | |
| } | |
| else if (selection.hasCirclesOrArcs()) { | |
| if (selection.has1Circle()) { makeCts_1Circle(selAllowed); } | |
| else if (selection.has2Circles()) { makeCts_2Circle(selAllowed); } | |
| } | |
| else if (selection.hasEllipseAndCo()) { | |
| if (selection.has1Ellipse()) { makeCts_1Ellipse(selAllowed); } | |
| if (selection.has2Ellipses()) { makeCts_2Ellipses(selAllowed); } | |
| } | |
| else if (selection.hasSplineAndCo()) { | |
| if (selection.has1Spline()) { makeCts_1Spline(selAllowed); } | |
| if (selection.has1SplineAndMore()) { makeCts_1SplineAndMore(selAllowed); } | |
| } | |
| // Make created constraints unselectable. | |
| if (selAllowed) { | |
| setDimsSelectability(false); | |
| } | |
| return selAllowed; | |
| } | |
| void makeCts_Faces(bool& selAllowed) | |
| { | |
| //area | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add area dimension")); | |
| createAreaDimension(selFaces[0]); | |
| selAllowed = true; | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_2Point(bool& selAllowed) | |
| { | |
| //distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distance dimension")); | |
| createDistanceDimension("Distance", { selPoints[0], selPoints[1] }); | |
| specialDimension = SpecialDimension::LineOr2PointsDistance; | |
| selAllowed = true; | |
| if (!isVerticalDistance({ selPoints[0], selPoints[1] })) { | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceX chamfer dimension")); | |
| createDistanceDimension("DistanceX", { selPoints[0], selPoints[1] }, true); | |
| specialDimension = SpecialDimension::LineOr2PointsChamfer; | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_3Point(bool& selAllowed) | |
| { | |
| // chain distances, angle | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal chain dimensions")); | |
| createChainDimension("DistanceX"); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal coordinate dimensions")); | |
| createCoordDimension("DistanceX"); | |
| } | |
| if (availableDimension == AvailableDimension::THIRD) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add 3-points angle dimension")); | |
| create3pAngleDimension({ selPoints[0], selPoints[1], selPoints[2] }); | |
| } | |
| else if (availableDimension == AvailableDimension::FOURTH) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add 3-points angle dimension")); | |
| create3pAngleDimension({ selPoints[1], selPoints[2], selPoints[0] }); | |
| } | |
| else if (availableDimension == AvailableDimension::FIFTH) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add 3-points angle dimension")); | |
| create3pAngleDimension({ selPoints[2], selPoints[0], selPoints[1] }); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_4MorePoints(bool& selAllowed) | |
| { | |
| // chain distances | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal chain dimension")); | |
| createChainDimension("DistanceX"); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal coordinate dimensions")); | |
| createCoordDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Point1Line(bool& selAllowed) | |
| { | |
| //distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add point to line distance dimension")); | |
| createDistanceDimension("Distance", { selPoints[0], selLine[0] }); | |
| selAllowed = true; | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Point1Circle(bool& selAllowed) | |
| { | |
| //Distance, extent distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add length dimension")); | |
| createDistanceDimension("Distance", { selPoints[0], selCircleArc[0] }); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Point1Ellipse(bool& selAllowed) | |
| { | |
| //Distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add length dimension")); | |
| createDistanceDimension("Distance", { selPoints[0], selEllipseArc[0] }); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Line(bool& selAllowed) | |
| { | |
| //distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add length dimension")); | |
| createDistanceDimension("Distance", { selLine[0] }); | |
| specialDimension = SpecialDimension::LineOr2PointsDistance; | |
| selAllowed = true; | |
| if (!isVerticalDistance({ selLine[0] })) { | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| // Potential improvement for the future: we could show available modes in cursor trail. | |
| //std::vector<QPixmap> pixmaps = { icon("TechDraw_LengthDimension"), icon("TechDraw_ExtensionCreateHorizChamferDimension") }; | |
| //addCursorTail(pixmaps); | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceX chamfer dimension")); | |
| createDistanceDimension("DistanceX", { selLine[0] }, true); | |
| specialDimension = SpecialDimension::LineOr2PointsChamfer; | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_2Line(bool& selAllowed) | |
| { | |
| //angle (if parallel: Distance (see in createAngleDimension)). | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add angle dimension")); | |
| createAngleDimension(selLine[0], selLine[1]); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Line1Circle(bool& selAllowed) | |
| { | |
| //distance, extent distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add circle to line distance dimension")); | |
| createDistanceDimension("Distance", { selCircleArc[0], selLine[0] }); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Line1Ellipse(bool& selAllowed) | |
| { | |
| //distance, extent distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add ellipse to line distance dimension")); | |
| createDistanceDimension("Distance", { selEllipseArc[0], selLine[0] }); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Circle(bool& selAllowed) | |
| { | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| createRadiusDiameterDimension(selCircleArc[0], true); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| createRadiusDiameterDimension(selCircleArc[0], false); | |
| if (selCircleArc[0].geomEdgeType() != GeomType::ARCOFCIRCLE) { | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| if (availableDimension == AvailableDimension::THIRD) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add arc length dimension")); | |
| createArcLengthDimension(selCircleArc[0]); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_2Circle(bool& selAllowed) | |
| { | |
| //Distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add circle to circle distance dimension")); | |
| createDistanceDimension("Distance", { selCircleArc[0], selCircleArc[1] }); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Ellipse(bool& selAllowed) | |
| { | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| createRadiusDiameterDimension(selEllipseArc[0], true); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| createRadiusDiameterDimension(selEllipseArc[0], false); | |
| if (selEllipseArc[0].geomEdgeType() != GeomType::ARCOFELLIPSE) { | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| if (availableDimension == AvailableDimension::THIRD) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add arc length dimension")); | |
| createArcLengthDimension(selEllipseArc[0]); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_2Ellipses(bool& selAllowed) | |
| { | |
| //Distance | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add ellipse to ellipse distance dimension")); | |
| createDistanceDimension("Distance", { selEllipseArc[0], selEllipseArc[1] }); | |
| selAllowed = true; | |
| } | |
| if (availableDimension == AvailableDimension::SECOND) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1Spline(bool& selAllowed) | |
| { | |
| //Edge length | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add edge length dimension")); | |
| createArcLengthDimension(selSplineAndCo[0]); | |
| selAllowed = true; | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void makeCts_1SplineAndMore(bool& selAllowed) | |
| { | |
| //Extend | |
| if (availableDimension == AvailableDimension::FIRST) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| selAllowed = true; | |
| availableDimension = AvailableDimension::RESET; | |
| } | |
| } | |
| void createAreaDimension(ReferenceEntry ref) | |
| { | |
| DrawViewDimension* dim = dimMaker(partFeat, "Area", { ref }, {}); | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void createRadiusDiameterDimension(ReferenceEntry ref, bool firstCstr) { | |
| int GeoId(TechDraw::DrawUtil::getIndexFromName(ref.getSubName())); | |
| TechDraw::BaseGeomPtr geom = partFeat->getGeomByIndex(GeoId); | |
| bool isCircleGeom = (geom->getGeomType() == GeomType::CIRCLE) || (geom->getGeomType() == GeomType::ELLIPSE); | |
| // Use same preference as in sketcher? | |
| ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/TechDraw/dimensioning"); | |
| bool dimensioningDiameter = hGrp->GetBool("DimensioningDiameter", true); | |
| bool dimensioningRadius = hGrp->GetBool("DimensioningRadius", true); | |
| DrawViewDimension* dim; | |
| if ((firstCstr && dimensioningRadius && !dimensioningDiameter) || | |
| (!firstCstr && !dimensioningRadius && dimensioningDiameter) || | |
| (firstCstr && dimensioningRadius && dimensioningDiameter && !isCircleGeom) || | |
| (!firstCstr && dimensioningRadius && dimensioningDiameter && isCircleGeom)) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add radius dimension")); | |
| dim = dimMaker(partFeat, "Radius", { ref }, {}); | |
| } | |
| else { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add diameter dimension")); | |
| dim = dimMaker(partFeat, "Diameter", { ref }, {}); | |
| } | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void createAngleDimension(ReferenceEntry ref1, ReferenceEntry ref2) { | |
| if (TechDraw::isValidMultiEdge({ ref1, ref2 }) != DimensionGeometry::isAngle) { | |
| //isValidMultiEdge check if lines are parallel. | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distance dimension")); | |
| createDistanceDimension("Distance", { ref1, ref2 }); | |
| return; | |
| } | |
| DrawViewDimension* dim = dimMaker(partFeat, "Angle", {ref1, ref2}, {}); | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void create3pAngleDimension(ReferenceVector refs) | |
| { | |
| DrawViewDimension* dim = dimMaker(partFeat, "Angle3Pt", refs, {}); | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void createArcLengthDimension(ReferenceEntry ref) | |
| { | |
| DrawViewDimension* dim = makeArcLengthDimension(ref); | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void createDistanceDimension(std::string type, ReferenceVector refs, bool chamfer = false) | |
| { | |
| DrawViewDimension* dim = dimMaker(partFeat, type, refs, {}); | |
| if (chamfer) { | |
| // Add the angle to the label | |
| TechDraw::pointPair pp = dim->getLinearPoints(); | |
| float dx = pp.first().x - pp.second().x; | |
| float dy = pp.first().y - pp.second().y; | |
| int alpha = std::round(Base::toDegrees(std::abs<float>(std::atan(type == "DistanceY" ? (dx / dy) : (dy / dx))))); | |
| std::string sAlpha = std::to_string(alpha); | |
| std::string formatSpec = dim->FormatSpec.getStrValue(); | |
| formatSpec = formatSpec + " x" + sAlpha + "°"; | |
| dim->FormatSpec.setValue(formatSpec); | |
| } | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void createExtentDistanceDimension(std::string type) { | |
| specialDimension = SpecialDimension::ExtendDistance; | |
| DrawViewDimension* dim = DrawDimHelper::makeExtentDim(partFeat, type, allRefs()); | |
| dims.push_back(dim); | |
| moveDimension(mousePos, dim); | |
| } | |
| void updateDistanceType() | |
| { | |
| if (dims.empty()) { | |
| return; | |
| } | |
| auto type = static_cast<DimensionType>(dims[0]->Type.getValue()); | |
| SpecialDimension backup = specialDimension; | |
| bool chamfer = specialDimension == SpecialDimension::LineOr2PointsChamfer; | |
| TechDraw::pointPair pp = dims[0]->getLinearPoints(); | |
| Base::Vector3d pnt1 = Rez::guiX(pp.first()); | |
| Base::Vector3d pnt2 = Rez::guiX(pp.second()); | |
| QPointF fpos = getDimPositionToBe(mousePos); | |
| double minX, minY, maxX, maxY; | |
| minX = min(pnt1.x, pnt2.x); | |
| maxX = max(pnt1.x, pnt2.x); | |
| minY = min(pnt1.y, pnt2.y); | |
| maxY = max(pnt1.y, pnt2.y); | |
| std::string newType = "Distance"; | |
| if (fpos.x() > minX && fpos.x() < maxX | |
| && (fpos.y() < minY || fpos.y() > maxY) && type != DimensionType::DistanceX) { | |
| if (chamfer) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceX chamfer dimension")); | |
| } | |
| else { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceX dimension")); | |
| } | |
| newType = "DistanceX"; | |
| } | |
| else if (fpos.y() > minY && fpos.y() < maxY | |
| && (fpos.x() < minX || fpos.x() > maxX) && type != DimensionType::DistanceY) { | |
| if (chamfer) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceY chamfer dimension")); | |
| } | |
| else { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceY dimension")); | |
| } | |
| newType = "DistanceY"; | |
| } | |
| else if ((((fpos.y() < minY || fpos.y() > maxY) && (fpos.x() < minX || fpos.x() > maxX)) | |
| || (fpos.y() > minY && fpos.y() < maxY && fpos.x() > minX && fpos.x() < maxX)) && type != DimensionType::Distance | |
| && !chamfer) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distance dimension")); | |
| } | |
| else { | |
| return; | |
| } | |
| specialDimension = backup; | |
| if (selLine.size() == 1) { | |
| createDistanceDimension(newType, { selLine[0] }, chamfer); | |
| } | |
| else { | |
| createDistanceDimension(newType, { selPoints[0], selPoints[1] }, chamfer); | |
| } | |
| setDimsSelectability(false); | |
| } | |
| void updateExtentDistanceType() | |
| { | |
| if (dims.empty()) { | |
| return; | |
| } | |
| auto type = static_cast<DimensionType>(dims[0]->Type.getValue()); | |
| TechDraw::pointPair pp = dims[0]->getLinearPoints(); | |
| Base::Vector3d pnt1 = Rez::guiX(pp.first()); | |
| Base::Vector3d pnt2 = Rez::guiX(pp.second()); | |
| QPointF fpos = getDimPositionToBe(mousePos); | |
| double minX, minY, maxX, maxY; | |
| minX = min(pnt1.x, pnt2.x); | |
| maxX = max(pnt1.x, pnt2.x); | |
| minY = min(pnt1.y, pnt2.y); | |
| maxY = max(pnt1.y, pnt2.y); | |
| if (fpos.x() > minX && fpos.x() < maxX | |
| && (fpos.y() < minY || fpos.y() > maxY) && type != DimensionType::DistanceX) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceX extent dimension")); | |
| createExtentDistanceDimension("DistanceX"); | |
| } | |
| else if (fpos.y() > minY && fpos.y() < maxY | |
| && (fpos.x() < minX || fpos.x() > maxX) && type != DimensionType::DistanceY) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add distanceY extent dimension")); | |
| createExtentDistanceDimension("DistanceY"); | |
| } | |
| else { | |
| return; | |
| } | |
| setDimsSelectability(false); | |
| } | |
| void updateChainDistanceType() | |
| { | |
| if (dims.empty()) { | |
| return; | |
| } | |
| double minX = std::numeric_limits<double>::max(); | |
| double minY = std::numeric_limits<double>::max(); | |
| double maxX = -std::numeric_limits<double>::max(); | |
| double maxY = -std::numeric_limits<double>::max(); | |
| for (auto dim : dims) { | |
| TechDraw::pointPair pp = dim->getLinearPoints(); | |
| Base::Vector3d pnt1 = Rez::guiX(pp.first()); | |
| Base::Vector3d pnt2 = Rez::guiX(pp.second()); | |
| minX = min(minX, min(pnt1.x, pnt2.x)); | |
| maxX = max(maxX, max(pnt1.x, pnt2.x)); | |
| minY = min(minY, min(pnt1.y, pnt2.y)); | |
| maxY = max(maxY, max(pnt1.y, pnt2.y)); | |
| } | |
| QPointF fpos = getDimPositionToBe(mousePos); | |
| auto type = static_cast<DimensionType>(dims[0]->Type.getValue()); | |
| if (fpos.x() > minX && fpos.x() < maxX | |
| && (fpos.y() < minY || fpos.y() > maxY) && type != DimensionType::DistanceX) { | |
| if (specialDimension == SpecialDimension::ChainDistance) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal chain dimensions")); | |
| createChainDimension("DistanceX"); | |
| } | |
| else { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal coord dimensions")); | |
| createCoordDimension("DistanceX"); | |
| } | |
| } | |
| else if (fpos.y() > minY && fpos.y() < maxY | |
| && (fpos.x() < minX || fpos.x() > maxX) && type != DimensionType::DistanceY) { | |
| if (specialDimension == SpecialDimension::ChainDistance) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add vertical chain dimensions")); | |
| createChainDimension("DistanceY"); | |
| } | |
| else { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add vertical coord dimensions")); | |
| createCoordDimension("DistanceY"); | |
| } | |
| } | |
| else if (((fpos.y() < minY || fpos.y() > maxY) && (fpos.x() < minX || fpos.x() > maxX)) && type != DimensionType::Distance) { | |
| if (specialDimension == SpecialDimension::ChainDistance) { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add oblique chain dimensions")); | |
| createChainDimension("Distance"); | |
| } | |
| else { | |
| restartCommand(QT_TRANSLATE_NOOP("Command", "Add oblique coord dimensions")); | |
| createCoordDimension("Distance"); | |
| } | |
| } | |
| else { | |
| return; | |
| } | |
| setDimsSelectability(false); | |
| } | |
| void createChainDimension(std::string type) | |
| { | |
| specialDimension = SpecialDimension::ChainDistance; | |
| if (type == "Distance") { | |
| dims = makeObliqueChainDimension(selPoints); | |
| } | |
| else { | |
| for (size_t i = 0; i < selPoints.size() - 1; ++i) { | |
| DrawViewDimension* dim = dimMaker(partFeat, type, { selPoints[i], selPoints[i + 1] }, {}); | |
| dims.push_back(dim); | |
| positionDimText(dim); | |
| } | |
| } | |
| } | |
| void createCoordDimension(std::string type) | |
| { | |
| specialDimension = SpecialDimension::CoordDistance; | |
| if (type == "Distance") { | |
| dims = makeObliqueCoordDimension(selPoints); | |
| } | |
| else { | |
| for (size_t i = 0; i < selPoints.size() - 1; ++i) { | |
| DrawViewDimension* dim = dimMaker(partFeat, type, { selPoints[0], selPoints[i + 1] }, {}); | |
| dims.push_back(dim); | |
| positionDimText(dim, i); | |
| } | |
| } | |
| } | |
| bool isVerticalDistance(ReferenceVector refs) | |
| { | |
| DimensionGeometry geometryRefs2d = validateDimSelection( | |
| refs, { "Edge", "Vertex" }, { 1, 2 }, { DimensionGeometry::isDiagonal }); | |
| return geometryRefs2d == DimensionGeometry::isDiagonal; | |
| } | |
| QPixmap icon(std::string name) | |
| { | |
| constexpr int width = 16; | |
| return Gui::BitmapFactory().pixmapFromSvg(name.c_str(), QSize(width, width)); | |
| } | |
| void restartCommand(const char* cstrName) { | |
| specialDimension = SpecialDimension::None; | |
| Gui::Command::abortCommand(); | |
| Gui::Command::openCommand(cstrName); | |
| dims.clear(); | |
| } | |
| void clearAndRestartCommand() { | |
| Gui::Command::abortCommand(); | |
| Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Dimension")); | |
| specialDimension = SpecialDimension::None; | |
| mousePos = QPoint(0,0); | |
| clearRefVectors(); | |
| partFeat = nullptr; | |
| dims.clear(); | |
| } | |
| void clearRefVectors() | |
| { | |
| selPoints.clear(); | |
| selLine.clear(); | |
| selCircleArc.clear(); | |
| selEllipseArc.clear(); | |
| selSplineAndCo.clear(); | |
| selFaces.clear(); | |
| } | |
| }; | |
| DEF_STD_CMD_A(CmdTechDrawDimension) | |
| CmdTechDrawDimension::CmdTechDrawDimension() | |
| : Command("TechDraw_Dimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts new contextual dimensions to the selection.\n" | |
| "Depending on your selection you might have several dimensions available. You can cycle through them using the M key.\n" | |
| "Left clicking on empty space will validate the current dimension. Right clicking or pressing Esc will cancel."); | |
| sWhatsThis = "TechDraw_Dimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_Dimension"; | |
| sAccel = "D"; | |
| } | |
| void CmdTechDrawDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| App::AutoTransaction::setEnable(false); | |
| ReferenceVector references2d; | |
| ReferenceVector references3d; | |
| TechDraw::DrawViewPart* partFeat = | |
| TechDraw::getReferencesFromSelection(references2d, references3d); | |
| activateHandler(new TDHandlerDimension(references2d, partFeat)); | |
| } | |
| bool CmdTechDrawDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| // Comp for dimension tools ============================================= | |
| class CmdTechDrawCompDimensionTools : public Gui::GroupCommand | |
| { | |
| public: | |
| CmdTechDrawCompDimensionTools() | |
| : GroupCommand("TechDraw_CompDimensionTools") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = "TechDraw"; | |
| sMenuText = QT_TR_NOOP("Dimension"); | |
| sToolTipText = QT_TR_NOOP("Dimension tools"); | |
| sWhatsThis = "TechDraw_CompDimensionTools"; | |
| sStatusTip = sToolTipText; | |
| setCheckable(false); | |
| setRememberLast(false); | |
| addCommand("TechDraw_Dimension"); | |
| addCommand(); //separator | |
| addCommand("TechDraw_LengthDimension"); | |
| addCommand("TechDraw_HorizontalDimension"); | |
| addCommand("TechDraw_VerticalDimension"); | |
| addCommand("TechDraw_RadiusDimension"); | |
| addCommand("TechDraw_DiameterDimension"); | |
| addCommand("TechDraw_AngleDimension"); | |
| addCommand("TechDraw_3PtAngleDimension"); | |
| addCommand("TechDraw_AreaDimension"); | |
| addCommand("TechDraw_ExtensionCreateLengthArc"); | |
| addCommand(); //separator | |
| addCommand("TechDraw_HorizontalExtentDimension"); | |
| addCommand("TechDraw_VerticalExtentDimension"); | |
| addCommand(); //separator | |
| addCommand("TechDraw_ExtensionCreateHorizChainDimension"); | |
| addCommand("TechDraw_ExtensionCreateVertChainDimension"); | |
| addCommand("TechDraw_ExtensionCreateObliqueChainDimension"); | |
| addCommand(); //separator | |
| addCommand("TechDraw_ExtensionCreateHorizCoordDimension"); | |
| addCommand("TechDraw_ExtensionCreateVertCoordDimension"); | |
| addCommand("TechDraw_ExtensionCreateObliqueCoordDimension"); | |
| addCommand(); //separator | |
| addCommand("TechDraw_ExtensionCreateHorizChamferDimension"); | |
| addCommand("TechDraw_ExtensionCreateVertChamferDimension"); | |
| } | |
| const char* className() const override { return "CmdTechDrawCompDimensionTools"; } | |
| bool isActive() override | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| }; | |
| //=========================================================================== | |
| // TechDraw_RadiusDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawRadiusDimension) | |
| CmdTechDrawRadiusDimension::CmdTechDrawRadiusDimension() | |
| : Command("TechDraw_RadiusDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Radius Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a radius dimension of a circular edge or arc"); | |
| sWhatsThis = "TechDraw_RadiusDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_RadiusDimension"; | |
| } | |
| void CmdTechDrawRadiusDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execRadius(this); | |
| } | |
| bool CmdTechDrawRadiusDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execRadius(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a radius dimension | |
| StringVector acceptableGeometry({"Edge"}); | |
| std::vector<int> minimumCounts({1}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys( | |
| {DimensionGeometry::isCircle, DimensionGeometry::isEllipse, DimensionGeometry::isBSplineCircle, DimensionGeometry::isBSpline}); | |
| execDim(cmd, "Radius", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_DiameterDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawDiameterDimension) | |
| CmdTechDrawDiameterDimension::CmdTechDrawDiameterDimension() | |
| : Command("TechDraw_DiameterDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Diameter Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a diameter dimension of a circular edge or arc"); | |
| sWhatsThis = "TechDraw_DiameterDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_DiameterDimension"; | |
| } | |
| void CmdTechDrawDiameterDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execDiameter(this); | |
| } | |
| bool CmdTechDrawDiameterDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execDiameter(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a diameter dimension | |
| StringVector acceptableGeometry({"Edge"}); | |
| std::vector<int> minimumCounts({1}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys( | |
| {DimensionGeometry::isCircle, DimensionGeometry::isEllipse, DimensionGeometry::isBSplineCircle, DimensionGeometry::isBSpline}); | |
| execDim(cmd, "Diameter", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_LengthDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawLengthDimension) | |
| CmdTechDrawLengthDimension::CmdTechDrawLengthDimension() | |
| : Command("TechDraw_LengthDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Length Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a length dimension of an edge or distance between two points"); | |
| sWhatsThis = "TechDraw_LengthDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_LengthDimension"; | |
| } | |
| void CmdTechDrawLengthDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execDistance(this); | |
| } | |
| bool CmdTechDrawLengthDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execDistance(Gui::Command* cmd) | |
| { | |
| StringVector acceptableGeometry({"Edge", "Vertex"}); | |
| std::vector<int> minimumCounts({1, 2}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys( | |
| {DimensionGeometry::isVertical, DimensionGeometry::isHorizontal, DimensionGeometry::isDiagonal, DimensionGeometry::isHybrid}); | |
| execDim(cmd, "Distance", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_HorizontalDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawHorizontalDimension) | |
| CmdTechDrawHorizontalDimension::CmdTechDrawHorizontalDimension() | |
| : Command("TechDraw_HorizontalDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Horizontal Length Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a horizontal length dimension of an edge or distance between two points"); | |
| sWhatsThis = "TechDraw_HorizontalDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_HorizontalDimension"; | |
| sAccel = "SHIFT+H"; | |
| } | |
| void CmdTechDrawHorizontalDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execDistanceX(this); | |
| } | |
| bool CmdTechDrawHorizontalDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execDistanceX(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a length dimension | |
| StringVector acceptableGeometry({"Edge", "Vertex"}); | |
| std::vector<int> minimumCounts({1, 2}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys({DimensionGeometry::isHorizontal, DimensionGeometry::isDiagonal, DimensionGeometry::isHybrid}); | |
| execDim(cmd, "DistanceX", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_VerticalDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawVerticalDimension) | |
| CmdTechDrawVerticalDimension::CmdTechDrawVerticalDimension() | |
| : Command("TechDraw_VerticalDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Vertical Length Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a vertical length dimension of an edge or distance between two points"); | |
| sWhatsThis = "TechDraw_VerticalDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_VerticalDimension"; | |
| sAccel = "SHIFT+V"; | |
| } | |
| void CmdTechDrawVerticalDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execDistanceY(this); | |
| } | |
| bool CmdTechDrawVerticalDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execDistanceY(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a length dimension | |
| StringVector acceptableGeometry({"Edge", "Vertex"}); | |
| std::vector<int> minimumCounts({1, 2}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys({DimensionGeometry::isVertical, DimensionGeometry::isDiagonal, DimensionGeometry::isHybrid}); | |
| execDim(cmd, "DistanceY", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_AngleDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawAngleDimension) | |
| CmdTechDrawAngleDimension::CmdTechDrawAngleDimension() | |
| : Command("TechDraw_AngleDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Angle Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts an angle dimension between two edges"); | |
| sWhatsThis = "TechDraw_AngleDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_AngleDimension"; | |
| } | |
| void CmdTechDrawAngleDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execAngle(this); | |
| } | |
| bool CmdTechDrawAngleDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execAngle(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a length dimension | |
| StringVector acceptableGeometry({"Edge"}); | |
| std::vector<int> minimumCounts({2}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys({DimensionGeometry::isAngle}); | |
| execDim(cmd, "Angle", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_3PtAngleDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDraw3PtAngleDimension) | |
| CmdTechDraw3PtAngleDimension::CmdTechDraw3PtAngleDimension() | |
| : Command("TechDraw_3PtAngleDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Angle Dimension From 3 Points"); | |
| sToolTipText = QT_TR_NOOP("Inserts an angle dimension between 3 selected points"); | |
| sWhatsThis = "TechDraw_3PtAngleDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_3PtAngleDimension"; | |
| } | |
| void CmdTechDraw3PtAngleDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execAngle3Pt(this); | |
| } | |
| bool CmdTechDraw3PtAngleDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execAngle3Pt(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a length dimension | |
| StringVector acceptableGeometry({"Vertex"}); | |
| std::vector<int> minimumCounts({3}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys({DimensionGeometry::isAngle3Pt}); | |
| execDim(cmd, "Angle3Pt", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_AreaDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawAreaDimension) | |
| CmdTechDrawAreaDimension::CmdTechDrawAreaDimension() | |
| : Command("TechDraw_AreaDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Area Annotation"); | |
| sToolTipText = QT_TR_NOOP("Inserts an annotation showing the area of a selected face"); | |
| sWhatsThis = "TechDraw_AreaDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_AreaDimension"; | |
| } | |
| void CmdTechDrawAreaDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execArea(this); | |
| } | |
| bool CmdTechDrawAreaDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execArea(Gui::Command* cmd) | |
| { | |
| //Define the geometric configuration required for a area dimension | |
| StringVector acceptableGeometry({"Face"}); | |
| std::vector<int> minimumCounts({1}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys({DimensionGeometry::isFace}); | |
| execDim(cmd, "Area", acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ExtentGroup | |
| //=========================================================================== | |
| DEF_STD_CMD_ACL(CmdTechDrawExtentGroup) | |
| CmdTechDrawExtentGroup::CmdTechDrawExtentGroup() | |
| : Command("TechDraw_ExtentGroup") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Extent Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a dimension showing the extent (overall length) of an object or feature"); | |
| sWhatsThis = "TechDraw_ExtentGroup"; | |
| sStatusTip = sToolTipText; | |
| // eType = ForEdit; | |
| } | |
| void CmdTechDrawExtentGroup::activated(int iMsg) | |
| { | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction); | |
| pcAction->setIcon(pcAction->actions().at(iMsg)->icon()); | |
| switch (iMsg) { | |
| case 0: | |
| execExtent(this, "DistanceX"); | |
| break; | |
| case 1: | |
| execExtent(this, "DistanceY"); | |
| break; | |
| default: | |
| Base::Console().message("CMD::ExtGrp - invalid iMsg: %d\n", iMsg); | |
| }; | |
| } | |
| Gui::Action* CmdTechDrawExtentGroup::createAction() | |
| { | |
| Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); | |
| pcAction->setDropDownMenu(true); | |
| applyCommandData(this->className(), pcAction); | |
| QAction* p1 = pcAction->addAction(QString()); | |
| p1->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_HorizontalExtentDimension")); | |
| p1->setObjectName(QStringLiteral("TechDraw_HorizontalExtentDimension")); | |
| p1->setWhatsThis(QStringLiteral("TechDraw_HorizontalExtentDimension")); | |
| QAction* p2 = pcAction->addAction(QString()); | |
| p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_VerticalExtentDimension")); | |
| p2->setObjectName(QStringLiteral("TechDraw_VerticalExtentDimension")); | |
| p2->setWhatsThis(QStringLiteral("TechDraw_VerticalExtentDimension")); | |
| _pcAction = pcAction; | |
| languageChange(); | |
| pcAction->setIcon(p1->icon()); | |
| int defaultId = 0; | |
| pcAction->setProperty("defaultAction", QVariant(defaultId)); | |
| return pcAction; | |
| } | |
| void CmdTechDrawExtentGroup::languageChange() | |
| { | |
| Command::languageChange(); | |
| if (!_pcAction) { | |
| return; | |
| } | |
| Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction); | |
| QList<QAction*> a = pcAction->actions(); | |
| QAction* arc1 = a[0]; | |
| arc1->setText(QApplication::translate("CmdTechDrawExtentGroup", "Horizontal extent")); | |
| arc1->setToolTip( | |
| QApplication::translate("TechDraw_HorizontalExtent", "Insert horizontal extent dimension")); | |
| arc1->setStatusTip(arc1->toolTip()); | |
| QAction* arc2 = a[1]; | |
| arc2->setText(QApplication::translate("CmdTechDrawExtentGroup", "Vertical extent")); | |
| arc2->setToolTip(QApplication::translate("TechDraw_VerticalExtentDimension", | |
| "Insert vertical extent dimension")); | |
| arc2->setStatusTip(arc2->toolTip()); | |
| } | |
| bool CmdTechDrawExtentGroup::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| //=========================================================================== | |
| // TechDraw_HorizontalExtentDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawHorizontalExtentDimension) | |
| CmdTechDrawHorizontalExtentDimension::CmdTechDrawHorizontalExtentDimension() | |
| : Command("TechDraw_HorizontalExtentDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Horizontal Extent Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a dimension showing the horizontal extent (overall length) of an object or feature."); | |
| sWhatsThis = "TechDraw_HorizontalExtentDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_HorizontalExtentDimension"; | |
| } | |
| void CmdTechDrawHorizontalExtentDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execExtent(this, "DistanceX"); | |
| } | |
| bool CmdTechDrawHorizontalExtentDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| void execExtent(Gui::Command* cmd, const std::string& dimType) | |
| { | |
| const char* commandString = nullptr; | |
| if (dimType == "DistanceX") { | |
| commandString = QT_TRANSLATE_NOOP("Command", "Create Dimension DistanceX"); | |
| } else if (dimType == "DistanceY") { | |
| commandString = QT_TRANSLATE_NOOP("Command", "Create Dimension DistanceY"); | |
| } | |
| Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", commandString)); | |
| bool result = _checkDrawViewPart(cmd); | |
| if (!result) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("No view of a part in selection.")); | |
| Gui::Command::abortCommand(); | |
| return; | |
| } | |
| ReferenceVector references2d; | |
| ReferenceVector references3d; | |
| TechDraw::DrawViewPart* partFeat = | |
| TechDraw::getReferencesFromSelection(references2d, references3d); | |
| // if sticky selection is in use we may get confusing selections that appear to | |
| // include both 2d and 3d geometry for the extent dim. | |
| if (!references3d.empty()) { | |
| for (auto& ref : references2d) { | |
| if (!ref.getSubName().empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("Selection contains both 2D and 3D geometry")); | |
| Gui::Command::abortCommand(); | |
| return; | |
| } | |
| } | |
| } | |
| //Define the geometric configuration required for a extent dimension | |
| StringVector acceptableGeometry({"Edge"}); | |
| std::vector<int> minimumCounts({1}); | |
| std::vector<DimensionGeometry> acceptableDimensionGeometrys({DimensionGeometry::isMultiEdge, | |
| DimensionGeometry::isHorizontal, | |
| DimensionGeometry::isVertical, | |
| DimensionGeometry::isDiagonal, | |
| DimensionGeometry::isCircle, | |
| DimensionGeometry::isEllipse, | |
| DimensionGeometry::isBSplineCircle, | |
| DimensionGeometry::isBSpline, | |
| DimensionGeometry::isZLimited}); | |
| //what 2d geometry configuration did we receive? | |
| DimensionGeometry geometryRefs2d = validateDimSelection( | |
| references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| if (geometryRefs2d == DimensionGeometry::isInvalid) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect Selection"), | |
| QObject::tr("Cannot make 2D extent dimension from selection")); | |
| Gui::Command::abortCommand(); | |
| return; | |
| } | |
| //what 3d geometry configuration did we receive? | |
| DimensionGeometry geometryRefs3d; | |
| if (geometryRefs2d == DimensionGeometry::isViewReference && !references3d.empty()) { | |
| geometryRefs3d = validateDimSelection3d(partFeat, | |
| references3d, | |
| acceptableGeometry, | |
| minimumCounts, | |
| acceptableDimensionGeometrys); | |
| if (geometryRefs3d == DimensionGeometry::isInvalid) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect Selection"), | |
| QObject::tr("Cannot make 3D extent dimension from selection")); | |
| Gui::Command::abortCommand(); | |
| return; | |
| } | |
| } | |
| if (references3d.empty()) { | |
| DrawDimHelper::makeExtentDim(partFeat, dimType, references2d); | |
| } | |
| else { | |
| DrawDimHelper::makeExtentDim3d(partFeat, dimType, references3d); | |
| } | |
| Gui::Command::commitCommand(); | |
| } | |
| //=========================================================================== | |
| // TechDraw_VerticalExtentDimension | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawVerticalExtentDimension) | |
| CmdTechDrawVerticalExtentDimension::CmdTechDrawVerticalExtentDimension() | |
| : Command("TechDraw_VerticalExtentDimension") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Vertical Extent Dimension"); | |
| sToolTipText = QT_TR_NOOP("Inserts a dimension showing the vertical extent (overall length) of an object or feature."); | |
| sWhatsThis = "TechDraw_VerticalExtentDimension"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_VerticalExtentDimension"; | |
| } | |
| void CmdTechDrawVerticalExtentDimension::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Task in progress"), | |
| QObject::tr("Close the active task dialog and try again")); | |
| return; | |
| } | |
| execExtent(this, "DistanceY"); | |
| } | |
| bool CmdTechDrawVerticalExtentDimension::isActive() | |
| { | |
| return isDimCmdActive(this); | |
| } | |
| //=========================================================================== | |
| // TechDraw_DimensionRepair | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawDimensionRepair) | |
| CmdTechDrawDimensionRepair::CmdTechDrawDimensionRepair() | |
| : Command("TechDraw_DimensionRepair") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Repair Dimension References"); | |
| sToolTipText = QT_TR_NOOP("Repairs broken or incorrect dimension references"); | |
| sWhatsThis = "TechDraw_DimensionRepair"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_DimensionRepair"; | |
| } | |
| void CmdTechDrawDimensionRepair::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| std::vector<App::DocumentObject*> dimObjs = | |
| getSelection().getObjectsOfType(TechDraw::DrawViewDimension::getClassTypeId()); | |
| TechDraw::DrawViewDimension* dim = nullptr; | |
| if (dimObjs.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("There is no dimension in your selection")); | |
| return; | |
| } else { | |
| dim = static_cast<TechDraw::DrawViewDimension*>(dimObjs.at(0)); | |
| } | |
| Gui::Control().showDialog(new TaskDlgDimReference(dim)); | |
| } | |
| bool CmdTechDrawDimensionRepair::isActive(void) | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveView = DrawGuiUtil::needView(this); | |
| bool taskInProgress = false; | |
| if (havePage) { | |
| taskInProgress = Gui::Control().activeDialog(); | |
| } | |
| return (havePage && haveView && !taskInProgress); | |
| } | |
| //------------------------------------------------------------------------------ | |
| void CreateTechDrawCommandsDims() | |
| { | |
| Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); | |
| rcCmdMgr.addCommand(new CmdTechDrawDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawRadiusDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawDiameterDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawLengthDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawHorizontalDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawVerticalDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawAngleDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDraw3PtAngleDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawAreaDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawExtentGroup()); | |
| rcCmdMgr.addCommand(new CmdTechDrawVerticalExtentDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawHorizontalExtentDimension()); | |
| rcCmdMgr.addCommand(new CmdTechDrawDimensionRepair()); | |
| rcCmdMgr.addCommand(new CmdTechDrawCompDimensionTools()); | |
| } | |
| //------------------------------------------------------------------------------ | |
| //Common code to build a dimension feature | |
| void execDim(Gui::Command* cmd, std::string type, StringVector acceptableGeometry, std::vector<int> minimumCounts, std::vector<DimensionGeometry> acceptableDimensionGeometrys) | |
| { | |
| bool result = _checkDrawViewPart(cmd); | |
| if (!result) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("No view of a part in selection.")); | |
| return; | |
| } | |
| ReferenceVector references2d; | |
| ReferenceVector references3d; | |
| TechDraw::DrawViewPart* partFeat = | |
| TechDraw::getReferencesFromSelection(references2d, references3d); | |
| //what 2d geometry configuration did we receive? | |
| DimensionGeometry geometryRefs2d = validateDimSelection( | |
| references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys); | |
| if (geometryRefs2d == DimensionGeometry::isInvalid) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("Cannot make 2D dimension from selection")); | |
| return; | |
| } | |
| //what 3d geometry configuration did we receive? | |
| DimensionGeometry geometryRefs3d{DimensionGeometry::isInvalid}; | |
| if (geometryRefs2d == DimensionGeometry::isViewReference && !references3d.empty()) { | |
| geometryRefs3d = validateDimSelection3d(partFeat, | |
| references3d, | |
| acceptableGeometry, | |
| minimumCounts, | |
| acceptableDimensionGeometrys); | |
| if (geometryRefs3d == DimensionGeometry::isInvalid) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect Selection"), | |
| QObject::tr("Cannot make 3D dimension from selection")); | |
| return; | |
| } | |
| } | |
| else { | |
| references3d.clear(); | |
| } | |
| //errors and warnings | |
| if (type == "Radius" || type == "Diameter") { | |
| if (geometryRefs2d == DimensionGeometry::isEllipse || geometryRefs3d == DimensionGeometry::isEllipse) { | |
| QMessageBox::StandardButton result = QMessageBox::warning( | |
| Gui::getMainWindow(), | |
| QObject::tr("Ellipse curve warning"), | |
| QObject::tr("Selected edge is an Ellipse. Value will be approximate. Continue?"), | |
| QMessageBox::Ok | QMessageBox::Cancel, | |
| QMessageBox::Cancel); | |
| if (result != QMessageBox::Ok) { | |
| return; | |
| } | |
| } | |
| if (geometryRefs2d == DimensionGeometry::isBSplineCircle || geometryRefs3d == DimensionGeometry::isBSplineCircle) { | |
| QMessageBox::StandardButton result = QMessageBox::warning( | |
| Gui::getMainWindow(), | |
| QObject::tr("B-spline curve warning"), | |
| QObject::tr("Selected edge is a B-spline. Value will be approximate. Continue?"), | |
| QMessageBox::Ok | QMessageBox::Cancel, | |
| QMessageBox::Cancel); | |
| if (result != QMessageBox::Ok) { | |
| return; | |
| } | |
| } | |
| if (geometryRefs2d == DimensionGeometry::isBSpline || geometryRefs3d == DimensionGeometry::isBSpline) { | |
| QMessageBox::critical( | |
| Gui::getMainWindow(), | |
| QObject::tr("B-spline curve error"), | |
| QObject::tr("Selected edge is a B-spline and a radius/diameter cannot be calculated.")); | |
| return; | |
| } | |
| } | |
| if (geometryRefs2d == DimensionGeometry::isFace && | |
| references2d.size() > 1) { | |
| Base::Console().warning("Multiple faces are selected. Using first.\n"); | |
| references2d.resize(1); | |
| } | |
| //build the dimension | |
| DrawViewDimension* dim = dimensionMaker(partFeat, type, references2d, references3d); | |
| if (type == "Distance" || type == "DistanceX" || type == "DistanceY" || type == "Angle" || type == "Angle3Pt") { | |
| //position the Dimension text on the view | |
| positionDimText(dim); | |
| } | |
| } | |
| DrawViewDimension* dimensionMaker(TechDraw::DrawViewPart* dvp, std::string dimType, | |
| ReferenceVector references2d, ReferenceVector references3d) | |
| { | |
| Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create dimension")); | |
| TechDraw::DrawViewDimension* dim = dimMaker(dvp, dimType, references2d, references3d); | |
| Gui::Command::commitCommand(); | |
| // Touch the parent feature so the dimension in tree view appears as a child | |
| dvp->touch(true); | |
| // Select only the newly created dimension | |
| Gui::Selection().clearSelection(); | |
| Gui::Selection().addSelection(dvp->getDocument()->getName(), dim->getNameInDocument()); | |
| return dim; | |
| } | |
| DrawViewDimension* dimMaker(TechDraw::DrawViewPart* dvp, std::string dimType, | |
| ReferenceVector references2d, ReferenceVector references3d) | |
| { | |
| TechDraw::DrawPage* page = dvp->findParentPage(); | |
| std::string PageName = page->getNameInDocument(); | |
| std::string dimName = dvp->getDocument()->getUniqueObjectName("Dimension"); | |
| Gui::Command::doCommand(Gui::Command::Doc, | |
| "App.activeDocument().addObject('TechDraw::DrawViewDimension', '%s')", | |
| dimName.c_str()); | |
| Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().%s.translateLabel('DrawViewDimension', 'Dimension', '%s')", | |
| dimName.c_str(), dimName.c_str()); | |
| Gui::Command::doCommand( | |
| Gui::Command::Doc, "App.activeDocument().%s.Type = '%s'", dimName.c_str(), dimType.c_str()); | |
| Gui::Command::doCommand(Gui::Command::Doc, | |
| "App.activeDocument().%s.MeasureType = '%s'", | |
| dimName.c_str(), | |
| "Projected"); | |
| auto* dim = dynamic_cast<TechDraw::DrawViewDimension*>(dvp->getDocument()->getObject(dimName.c_str())); | |
| if (!dim) { | |
| throw Base::TypeError("CmdTechDrawNewDiameterDimension - dim not found\n"); | |
| } | |
| //always have References2D, even if only for the parent DVP | |
| dim->setReferences2d(references2d); | |
| dim->setReferences3d(references3d); | |
| Gui::Command::doCommand(Gui::Command::Doc, | |
| "App.activeDocument().%s.addView(App.activeDocument().%s)", | |
| PageName.c_str(), | |
| dimName.c_str()); | |
| dim->recomputeFeature(); | |
| return dim; | |
| } | |
| //position the Dimension text on the view | |
| void positionDimText(DrawViewDimension* dim, int offsetIndex) | |
| { | |
| TechDraw::pointPair pp = dim->getLinearPoints(); | |
| Base::Vector3d mid = (pp.first() + pp.second()) / 2.0; | |
| dim->X.setValue(mid.x); | |
| double fontSize = Preferences::dimFontSizeMM(); | |
| dim->Y.setValue(-mid.y + (offsetIndex * 1.5 + 0.5) * fontSize); | |
| } | |
| //=========================================================================== | |
| // Selection Validation Helpers | |
| //=========================================================================== | |
| //! common checks of Selection for Dimension commands | |
| //non-empty selection, no more than maxObjs selected and at least 1 DrawingPage exists | |
| bool _checkSelection(Gui::Command* cmd, unsigned maxObjs) | |
| { | |
| std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx(); | |
| if (selection.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("Select an object first")); | |
| return false; | |
| } | |
| const std::vector<std::string> SubNames = selection[0].getSubNames(); | |
| if (SubNames.size() > maxObjs) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("Too many objects selected")); | |
| return false; | |
| } | |
| std::vector<App::DocumentObject*> pages = | |
| cmd->getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); | |
| if (pages.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("Incorrect selection"), | |
| QObject::tr("Create a page first.")); | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool _checkDrawViewPart(Gui::Command* cmd) | |
| { | |
| std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx(); | |
| for (auto& sel : selection) { | |
| auto dvp = dynamic_cast<TechDraw::DrawViewPart*>(sel.getObject()); | |
| if (dvp) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |