Files
create/src/Mod/TechDraw/Gui/CommandCreateDims.cpp

2725 lines
103 KiB
C++

/***************************************************************************
* 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <string>
#include <vector>
#include <QApplication>
#include <QMessageBox>
#include <QKeyEvent>
#include <QMouseEvent>
#endif//#ifndef _PreComp_
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Base/Console.h>
#include <Gui/Action.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Gui/SelectionObject.h>
#include <Mod/TechDraw/App/DrawDimHelper.h>
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/Geometry.h>
#include <Mod/TechDraw/App/LandmarkDimension.h>
#include <Mod/TechDraw/App/Preferences.h>
#include "CommandExtensionDims.h"
#include "DimensionValidators.h"
#include "DrawGuiUtil.h"
#include "QGIViewDimension.h"
#include "QGVPage.h"
#include "MDIViewPage.h"
#include "TaskDimRepair.h"
#include "TaskLinkDim.h"
#include "TaskSelectLineAttributes.h"
#include "TechDrawHandler.h"
#include "ViewProviderDimension.h"
#include "ViewProviderDrawingView.h"
#include "ViewProviderDrawingView.h"
using namespace TechDrawGui;
using namespace TechDraw;
using namespace std;
using DimensionType = TechDraw::DrawViewDimension::DimensionType;
//===========================================================================
// utility routines
//===========================================================================
//internal functions
bool _checkSelection(Gui::Command* cmd, unsigned maxObjs = 2);
bool _checkDrawViewPart(Gui::Command* cmd);
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 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)
{
auto* mdi = dynamic_cast<MDIViewPage*>(Gui::getMainWindow()->activeWindow());
if (!mdi) {
return;
}
ViewProviderPage* vp = mdi->getViewProviderPage();
if (!vp) {
return;
}
QGVPage* viewPage = vp->getQGVPage();
if (!viewPage) {
return;
}
viewPage->activateHandler(newHandler);
}
//===========================================================================
// 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)
, previousPos(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,
ExtendDistance,
ChainDistance,
CoordDistance,
None
};
void activated() override
{
Gui::Selection().setSelectionStyle(Gui::SelectionSingleton::SelectionStyle::GreedySelection);
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Insert Dimension"));
handleInitialSelection();
}
void deactivated() override
{
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(previousPos);
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
{
previousPos = 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){
updateDistanceType(event->pos());
}
else if (specialDimension == SpecialDimension::ExtendDistance){
updateExtentDistanceType(event->pos());
}
else if (specialDimension == SpecialDimension::ChainDistance || specialDimension == SpecialDimension::CoordDistance){
updateChainDistanceType(event->pos());
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(event->pos(), dim, textToMiddle, dirMaster, delta, dimType, i);
if (specialDimension == SpecialDimension::CoordDistance) {
i++;
}
}
}
QGIDatumLabel* getDimLabel(DrawViewDimension* d)
{
auto* vp = dynamic_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 = dynamic_cast<ViewProviderDrawingView*>(Gui::Application::Instance->getViewProvider(partFeat));
if (!vpp) { return QPointF(); }
QPointF scenePos = viewPage->mapToScene(pos) - vpp->getQView()->pos();
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 = scenePos.y() + i * 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 = scenePos.x() + i * 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);
}
}
bool mousePressEvent(QMouseEvent* event) override
{
if (event->button() == Qt::RightButton && !dims.empty()) {
Gui::Selection().clearSelection();
clearAndRestartCommand();
event->accept();
return true;
}
return TechDrawHandler::mousePressEvent(event);
}
bool mouseReleaseEvent(QMouseEvent* event) override
{
//Base::Console().Warning("mouseReleaseEvent TH\n");
bool finalize = true;
if (removedRef.hasGeometry()) {
finalize = false;
//Base::Console().Warning("RmvSelection \n");
// Remove the reference from the vector
ReferenceVector& selVector = getSelectionVector(removedRef);
selVector.erase(std::remove(selVector.begin(), selVector.end(), removedRef), selVector.end());
if (!selectionEmpty()) {
availableDimension = AvailableDimension::FIRST;
makeAppropriateDimension(event->pos());
}
else {
clearAndRestartCommand();
}
removedRef = ReferenceEntry();
}
if (addedRef.hasGeometry()) {
finalize = false;
//Base::Console().Warning("AddSelection\n");
//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", event->pos());
}
}
else {
Base::Console().Warning("h4\n");
ReferenceVector& selVector = getSelectionVector(addedRef);
selVector.push_back(addedRef);
availableDimension = AvailableDimension::FIRST;
bool selAllowed = makeAppropriateDimension(event->pos());
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();
}
return true;
}
void onSelectionChanged(const Gui::SelectionChanges& msg)
{
Base::Console().Warning("onSelectionChanged %d - --%s--\n", (int)msg.Type, msg.pSubName);
if (msg.Type == Gui::SelectionChanges::ClrSelection) {
//clearAndRestartCommand();
return;
}
if (msg.Object.getObjectName().empty()
|| msg.Object.getDocument() != getPage()->getDocument()) {
if (msg.Type == Gui::SelectionChanges::AddSelection) {
Gui::Selection().rmvSelection(msg.pDocName, msg.pObjectName, msg.pSubName);
}
return;
}
/*if (msg.Type == Gui::SelectionChanges::SetPreselect) {
Base::Console().Warning("SetPreselect\n");
std::string geomName = DrawUtil::getGeomTypeFromName(msg.pSubName);
edgeOrPointPreselected = geomName == "Edge" || geomName == "Vertex";
return;
}
else if (msg.Type == Gui::SelectionChanges::RmvPreselect) {
Base::Console().Warning("RmvPreselect\n");
edgeOrPointPreselected = false;
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 QString::fromLatin1("TechDraw_Dimension_Pointer");
}
protected:
SpecialDimension specialDimension;
AvailableDimension availableDimension;
QPoint previousPos;
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;
// 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(QPoint());
if (!selAllowed) {
clearRefVectors();
}
}
void finalizeCommand()
{
//Base::Console().Warning("finalizeCommand \n");
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() == TechDraw::GENERIC) {
TechDraw::GenericPtr gen1 = std::static_pointer_cast<TechDraw::Generic>(geom);
if (gen1->points.size() < 2) {
return emptyVector;
}
return selLine;
//Base::Vector3d line = gen1->points.at(1) - gen1->points.at(0);
}
else if (geom->getGeomType() == TechDraw::CIRCLE || geom->getGeomType() == TechDraw::ARCOFCIRCLE) {
return selCircleArc;
}
else if (geom->getGeomType() == TechDraw::ELLIPSE || geom->getGeomType() == TechDraw::ARCOFELLIPSE) {
return selEllipseArc;
}
else if (geom->getGeomType() == TechDraw::BSPLINE) {
//TechDraw::BSplinePtr spline = std::static_pointer_cast<TechDraw::BSpline>(geom);
//if (spline->isCircle()) {
// return isBSplineCircle;
//}
//else {
//}
return selSplineAndCo;
}
}
else if (geomName == "Vertex") {
return selPoints;
}
return emptyVector;
}
/*
bool notSelectedYet(const ReferenceEntry& elem)
{
auto contains = [&](const ReferenceVector& vec, const ReferenceEntry& elem) {
for (const auto& x : vec)
{
if (x == elem){
return true;
}
}
return false;
};
return !contains(selPoints, elem)
&& !contains(selLine, elem)
&& !contains(selCircleArc, elem)
&& !contains(selEllipseArc, elem)
&& !contains(selFaces, elem);
}*/
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(QPoint& pos) {
bool selAllowed = false;
//Base::Console().Warning("makeAppropriateDimension %d %d %d %d %d %d\n", selPoints.size(), selLine.size(), selCircleArc.size(), selEllipseArc.size(), selSplineAndCo.size(), selFaces.size());
GeomSelectionSizes selection(selPoints.size(), selLine.size(), selCircleArc.size(), selEllipseArc.size(), selSplineAndCo.size(), selFaces.size());
if (selection.hasFaces()) {
makeCts_Faces(selAllowed, pos);
}
else if (selection.hasPoints()) {
if (selection.has1Point()) { selAllowed = true; }
else if (selection.has2Points()) { makeCts_2Point(selAllowed, pos); }
else if (selection.has3Points()) { makeCts_3Point(selAllowed, pos); }
else if (selection.has4MorePoints()) { makeCts_4MorePoints(selAllowed, pos); }
else if (selection.has1Point1Line()) { makeCts_1Point1Line(selAllowed, pos); }
else if (selection.has1Point1Circle()) { makeCts_1Point1Circle(selAllowed, pos); }
else if (selection.has1Point1Ellipse()) { makeCts_1Point1Ellipse(selAllowed, pos); }
}
else if (selection.hasLines()) {
if (selection.has1Line()) { makeCts_1Line(selAllowed, pos); }
else if (selection.has2Lines()) { makeCts_2Line(selAllowed, pos); }
else if (selection.has1Line1Circle()) { makeCts_1Line1Circle(selAllowed, pos); }
else if (selection.has1Line1Ellipse()) { makeCts_1Line1Ellipse(selAllowed, pos); }
}
else if (selection.hasCirclesOrArcs()) {
if (selection.has1Circle()) { makeCts_1Circle(selAllowed, pos); }
else if (selection.has2Circles()) { makeCts_2Circle(selAllowed, pos); }
}
else if (selection.hasEllipseAndCo()) {
if (selection.has1Ellipse()) { makeCts_1Ellipse(selAllowed, pos); }
if (selection.has2Ellipses()) { makeCts_2Ellipses(selAllowed, pos); }
}
else if (selection.hasSplineAndCo()) {
if (selection.has1Spline()) { makeCts_1Spline(selAllowed, pos); }
if (selection.has1SplineAndMore()) { makeCts_1SplineAndMore(selAllowed, pos); }
}
return selAllowed;
}
// TODO
void makeCts_Faces(bool& selAllowed, QPoint& pos)
{
//area
if (availableDimension == AvailableDimension::FIRST) {
/*restartCommand(QT_TRANSLATE_NOOP("Command", "Add Area dimension"));
createAreaDimension(pos);
selAllowed = true;
availableDimension = AvailableDimension::RESET;*/
}
}
void makeCts_2Point(bool& selAllowed, QPoint& pos)
{
//distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Distance dimension"));
createDistanceDimension("Distance", selPoints[0], selPoints[1], pos);
specialDimension = SpecialDimension::LineOr2PointsDistance;
selAllowed = true;
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_3Point(bool& selAllowed, QPoint& pos)
{
// chain distances, angle
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal chain dimensions"));
createChainDimension("DistanceX", pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal coordinate dimensions"));
createCoordDimension("DistanceX", pos);
}
if (availableDimension == AvailableDimension::THIRD) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add 3-points angle dimension"));
create3pAngleDimension(selPoints[0], selPoints[1], selPoints[2], pos);
}
else if (availableDimension == AvailableDimension::FOURTH) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add 3-points angle dimension"));
create3pAngleDimension(selPoints[1], selPoints[2], selPoints[0], pos);
}
else if (availableDimension == AvailableDimension::FIFTH) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add 3-points angle dimension"));
create3pAngleDimension(selPoints[2], selPoints[0], selPoints[1], pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_4MorePoints(bool& selAllowed, QPoint& pos)
{
// chain distances
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal chain dimension"));
createChainDimension("DistanceX", pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal coordinate dimensions"));
createCoordDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Point1Line(bool& selAllowed, QPoint& pos)
{
//distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add point to line Distance dimension"));
createDistanceDimension("Distance", selPoints[0], selLine[0], pos);
selAllowed = true;
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Point1Circle(bool& selAllowed, QPoint& pos)
{
//Distance, extent distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add length dimension"));
createDistanceDimension("Distance", selPoints[0], selCircleArc[0], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Point1Ellipse(bool& selAllowed, QPoint& pos)
{
//Distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add length dimension"));
createDistanceDimension("Distance", selPoints[0], selEllipseArc[0], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Line(bool& selAllowed, QPoint& pos)
{
//distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add length dimension"));
createDistanceDimension("Distance", selLine[0], ReferenceEntry(), pos);
specialDimension = SpecialDimension::LineOr2PointsDistance;
selAllowed = true;
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_2Line(bool& selAllowed, QPoint& pos)
{
//angle (if parallel: Distance (see in createAngleDimension)).
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Angle dimension"));
createAngleDimension(selLine[0], selLine[1], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Line1Circle(bool& selAllowed, QPoint& pos)
{
//distance, extent distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add circle to line Distance dimension"));
createDistanceDimension("Distance", selCircleArc[0], selLine[0], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Line1Ellipse(bool& selAllowed, QPoint& pos)
{
//distance, extent distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add ellipse to line Distance dimension"));
createDistanceDimension("Distance", selEllipseArc[0], selLine[0], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Circle(bool& selAllowed, QPoint& pos)
{
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Radius dimension"));
createRadiusDiameterDimension(selCircleArc[0], pos, true);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Radius dimension"));
createRadiusDiameterDimension(selCircleArc[0], pos, false);
if (selCircleArc[0].geomEdgeType() != TechDraw::ARCOFCIRCLE) {
availableDimension = AvailableDimension::RESET;
}
}
if (availableDimension == AvailableDimension::THIRD) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Arc Length dimension"));
createArcLengthDimension(selCircleArc[0], pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_2Circle(bool& selAllowed, QPoint& pos)
{
//Distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add circle to circle Distance dimension"));
createDistanceDimension("Distance", selCircleArc[0], selCircleArc[1], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Ellipse(bool& selAllowed, QPoint& pos)
{
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Radius dimension"));
createRadiusDiameterDimension(selEllipseArc[0], pos, true);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Radius dimension"));
createRadiusDiameterDimension(selEllipseArc[0], pos, false);
if (selEllipseArc[0].geomEdgeType() != TechDraw::ARCOFELLIPSE) {
availableDimension = AvailableDimension::RESET;
}
}
if (availableDimension == AvailableDimension::THIRD) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Arc Length dimension"));
createArcLengthDimension(selEllipseArc[0], pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_2Ellipses(bool& selAllowed, QPoint& pos)
{
//Distance
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add ellipse to ellipse Distance dimension"));
createDistanceDimension("Distance", selEllipseArc[0], selEllipseArc[1], pos);
selAllowed = true;
}
if (availableDimension == AvailableDimension::SECOND) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1Spline(bool& selAllowed, QPoint& pos)
{
//Edge length
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add edge length dimension"));
createArcLengthDimension(selSplineAndCo[0], pos);
selAllowed = true;
availableDimension = AvailableDimension::RESET;
}
}
void makeCts_1SplineAndMore(bool& selAllowed, QPoint& pos)
{
//Extend
if (availableDimension == AvailableDimension::FIRST) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Extent dimension"));
createExtentDistanceDimension("DistanceX", pos);
selAllowed = true;
availableDimension = AvailableDimension::RESET;
}
}
//TODO
void createAreaDimension(QPoint& pos)
{
/*// see CmdTechDrawExtensionAreaAnnotation::activated
Base::Vector3d center;
double totalArea = 0.0;
for (auto& ref : selFaces) {
TechDraw::FacePtr face = partFeat->getFace(ref.getSubName());
if (!face) {
continue;
}
GProp_GProps faceProps;
BRepGProp::SurfaceProperties(face->toOccFace(), faceProps);
double faceArea = faceProps.Mass();
totalArea += faceArea;
center += faceArea * DrawUtil::toVector3d(faceProps.CentreOfMass());
}
if (totalArea > 0.0) {
center /= totalArea;
}
//function (and file) to create in CommandExtensionPack.h
auto* areaBalloon = createAreaBalloon(totalArea, center);*/
}
void createRadiusDiameterDimension(ReferenceEntry ref, QPoint& pos, bool firstCstr) {
bool isCircleGeom = true;
int GeoId(TechDraw::DrawUtil::getIndexFromName(ref.getSubName()));
TechDraw::BaseGeomPtr geom = partFeat->getGeomByIndex(GeoId);
isCircleGeom = geom->getGeomType() == TechDraw::CIRCLE || TechDraw::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)) {
dim = dimMaker(partFeat, "Radius", { ref }, {});
}
else {
dim = dimMaker(partFeat, "Diameter", { ref }, {});
}
dims.push_back(dim);
moveDimension(pos, dim);
}
void createAngleDimension(ReferenceEntry ref1, ReferenceEntry ref2, QPoint& pos) {
if (TechDraw::isValidMultiEdge({ ref1, ref2 }) != isAngle) {
//isValidMultiEdge check if lines are parallel.
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Distance dimension"));
createDistanceDimension("Distance", ref1, ref2, pos);
return;
}
DrawViewDimension* dim = dimMaker(partFeat, "Angle", {ref1, ref2}, {});
dims.push_back(dim);
moveDimension(pos, dim);
}
void create3pAngleDimension(ReferenceEntry ref1, ReferenceEntry ref2, ReferenceEntry ref3, QPoint& pos)
{
DrawViewDimension* dim = dimMaker(partFeat, "Angle3Pt", {ref1, ref2, ref3}, {});
dims.push_back(dim);
moveDimension(pos, dim);
}
void createArcLengthDimension(ReferenceEntry ref, QPoint& pos)
{
DrawViewDimension* dim = makeArcLengthDimension(ref);
dims.push_back(dim);
moveDimension(pos, dim);
}
void createDistanceDimension(std::string type, ReferenceEntry ref1, ReferenceEntry ref2, QPoint& pos) {
ReferenceVector refs = { ref1 };
if (ref2.hasGeometry()) { // if valid
refs.push_back(ref2);
}
DrawViewDimension* dim = dimMaker(partFeat, type, refs, {});
dims.push_back(dim);
moveDimension(pos, dim);
}
void createExtentDistanceDimension(std::string type, QPoint& pos) {
specialDimension = SpecialDimension::ExtendDistance;
DrawViewDimension* dim = DrawDimHelper::makeExtentDim(partFeat, type, allRefs());
dims.push_back(dim);
moveDimension(pos, dim);
}
void updateDistanceType(QPoint& pos)
{
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(pos);
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) {
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) {
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) {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add Distance dimension"));
}
else {
return;
}
specialDimension = SpecialDimension::LineOr2PointsDistance;
if (selLine.size() == 1) {
createDistanceDimension(newType, selLine[0], ReferenceEntry(), pos);
}
else {
createDistanceDimension(newType, selPoints[0], selPoints[1], pos);
}
}
void updateExtentDistanceType(QPoint& pos)
{
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(pos);
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", pos);
}
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", pos);
}
}
void updateChainDistanceType(QPoint& pos)
{
if (dims.empty()) {
return;
}
double minX = DBL_MAX;
double minY = DBL_MAX;
double maxX = -DBL_MAX;
double maxY = -DBL_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(pos);
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", pos);
}
else {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add horizontal coord dimensions"));
createCoordDimension("DistanceX", pos);
}
}
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", pos);
}
else {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add vertical coord dimensions"));
createCoordDimension("DistanceY", pos);
}
}
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", pos);
}
else {
restartCommand(QT_TRANSLATE_NOOP("Command", "Add oblique coord dimensions"));
createCoordDimension("Distance", pos);
}
}
}
void createChainDimension(std::string type, QPoint& pos)
{
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, QPoint& pos)
{
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);
}
}
}
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;
previousPos = 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("Insert Dimension");
sToolTipText = QT_TR_NOOP("Dimension contextually based on your 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 Dimensiont. Right clicking or pressing Esc will cancel.");
sWhatsThis = "TechDraw_Dimension";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_Dimension";
}
void CmdTechDrawDimension::activated(int iMsg)
{
Q_UNUSED(iMsg);
ReferenceVector references2d;
ReferenceVector references3d;
TechDraw::DrawViewPart* partFeat =
TechDraw::getReferencesFromSelection(references2d, references3d);
activateHandler(new TDHandlerDimension(references2d, partFeat));
}
bool CmdTechDrawDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
// 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;
eType = ForEdit;
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_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");
}
const char* className() const override { return "CmdTechDrawCompDimensionTools"; }
};
//===========================================================================
// TechDraw_RadiusDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawRadiusDimension)
CmdTechDrawRadiusDimension::CmdTechDrawRadiusDimension()
: Command("TechDraw_RadiusDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Radius Dimension");
sToolTipText = sMenuText;
sWhatsThis = "TechDraw_RadiusDimension";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_RadiusDimension";
sAccel = "D";
eType = ForEdit;
}
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 active task dialog and try again."));
return;
}
execRadius(this);
}
bool CmdTechDrawRadiusDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execRadius(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a radius dimension
StringVector acceptableGeometry({"Edge"});
std::vector<int> minimumCounts({1});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys(
{isCircle, isEllipse, isBSplineCircle, isBSpline});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d radius dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d(isInvalid);
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d radius dimension from selection"));
return;
}
}
//errors and warnings
if (geometryRefs2d == isEllipse || geometryRefs3d == isEllipse) {
QMessageBox::StandardButton result = QMessageBox::warning(
Gui::getMainWindow(),
QObject::tr("Ellipse Curve Warning"),
QObject::tr("Selected edge is an Ellipse. Radius will be approximate. Continue?"),
QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Cancel);
if (result != QMessageBox::Ok) {
return;
}
}
if (geometryRefs2d == isBSplineCircle || geometryRefs3d == isBSplineCircle) {
QMessageBox::StandardButton result = QMessageBox::warning(
Gui::getMainWindow(),
QObject::tr("BSpline Curve Warning"),
QObject::tr("Selected edge is a BSpline. Radius will be approximate. Continue?"),
QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Cancel);
if (result != QMessageBox::Ok) {
return;
}
}
if (geometryRefs2d == isBSpline || geometryRefs3d == isBSpline) {
QMessageBox::critical(
Gui::getMainWindow(),
QObject::tr("BSpline Curve Error"),
QObject::tr("Selected edge is a BSpline and a radius can not be calculated."));
return;
}
//build the dimension
// DrawViewDimension* dim =
dimensionMaker(partFeat, "Radius", references2d, references3d);
}
//===========================================================================
// TechDraw_DiameterDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawDiameterDimension)
CmdTechDrawDiameterDimension::CmdTechDrawDiameterDimension()
: Command("TechDraw_DiameterDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Diameter Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execDiameter(this);
}
bool CmdTechDrawDiameterDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execDiameter(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a diameter dimension
StringVector acceptableGeometry({"Edge"});
std::vector<int> minimumCounts({1});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys(
{isCircle, isEllipse, isBSplineCircle, isBSpline});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d diameter dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d(isInvalid);
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d diameter dimension from selection"));
return;
}
}
//errors and warnings
if (geometryRefs2d == isEllipse || geometryRefs3d == isEllipse) {
QMessageBox::StandardButton result = QMessageBox::warning(
Gui::getMainWindow(),
QObject::tr("Ellipse Curve Warning"),
QObject::tr("Selected edge is an Ellipse. Diameter will be approximate. Continue?"),
QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Cancel);
if (result != QMessageBox::Ok) {
return;
}
}
if (geometryRefs2d == isBSplineCircle || geometryRefs3d == isBSplineCircle) {
QMessageBox::StandardButton result = QMessageBox::warning(
Gui::getMainWindow(),
QObject::tr("BSpline Curve Warning"),
QObject::tr("Selected edge is a BSpline. Diameter will be approximate. Continue?"),
QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Cancel);
if (result != QMessageBox::Ok) {
return;
}
}
if (geometryRefs2d == isBSpline || geometryRefs3d == isBSpline) {
QMessageBox::critical(
Gui::getMainWindow(),
QObject::tr("BSpline Curve Error"),
QObject::tr("Selected edge is a BSpline and a diameter can not be calculated."));
return;
}
//build the dimension
// DrawViewDimension* dim =
dimensionMaker(partFeat, "Diameter", references2d, references3d);
}
//===========================================================================
// TechDraw_LengthDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawLengthDimension)
CmdTechDrawLengthDimension::CmdTechDrawLengthDimension()
: Command("TechDraw_LengthDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Length Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execDistance(this);
}
bool CmdTechDrawLengthDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execDistance(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry({"Edge", "Vertex"});
std::vector<int> minimumCounts({1, 2});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys(
{isVertical, isHorizontal, isDiagonal, isHybrid});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d linear dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d;
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d linear dimension from selection"));
return;
}
}
//build the dimension
DrawViewDimension* dim = dimensionMaker(partFeat, "Distance", references2d, references3d);
//position the Dimension text on the view
positionDimText(dim);
}
//===========================================================================
// TechDraw_HorizontalDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawHorizontalDimension)
CmdTechDrawHorizontalDimension::CmdTechDrawHorizontalDimension()
: Command("TechDraw_HorizontalDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Horizontal Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execDistanceX(this);
}
bool CmdTechDrawHorizontalDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execDistanceX(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry({"Edge", "Vertex"});
std::vector<int> minimumCounts({1, 2});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys({isHorizontal, isDiagonal, isHybrid});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d horizontal dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d;
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isInvalid) {
QMessageBox::warning(
Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d horizontal dimension from selection"));
return;
}
}
//build the dimension
DrawViewDimension* dim = dimensionMaker(partFeat, "DistanceX", references2d, references3d);
//position the Dimension text on the view
positionDimText(dim);
}
//===========================================================================
// TechDraw_VerticalDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawVerticalDimension)
CmdTechDrawVerticalDimension::CmdTechDrawVerticalDimension()
: Command("TechDraw_VerticalDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Vertical Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execDistanceY(this);
}
bool CmdTechDrawVerticalDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execDistanceY(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry({"Edge", "Vertex"});
std::vector<int> minimumCounts({1, 2});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys({isVertical, isDiagonal, isHybrid});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d vertical dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d;
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isVertical) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d vertical dimension from selection"));
return;
}
}
//build the dimension
DrawViewDimension* dim = dimensionMaker(partFeat, "DistanceY", references2d, references3d);
//position the Dimension text on the view
positionDimText(dim);
}
//===========================================================================
// TechDraw_AngleDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawAngleDimension)
CmdTechDrawAngleDimension::CmdTechDrawAngleDimension()
: Command("TechDraw_AngleDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Angle Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execAngle(this);
}
bool CmdTechDrawAngleDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execAngle(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry({"Edge"});
std::vector<int> minimumCounts({2});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys({isAngle});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d angle dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d;
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d angle dimension from selection"));
return;
}
}
//build the dimension
DrawViewDimension* dim = dimensionMaker(partFeat, "Angle", references2d, references3d);
//position the Dimension text on the view
positionDimText(dim);
}
//===========================================================================
// TechDraw_3PtAngleDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDraw3PtAngleDimension)
CmdTechDraw3PtAngleDimension::CmdTechDraw3PtAngleDimension()
: Command("TechDraw_3PtAngleDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert 3-Point Angle Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execAngle3Pt(this);
}
bool CmdTechDraw3PtAngleDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
void execAngle3Pt(Gui::Command* cmd)
{
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);
//Define the geometric configuration required for a length dimension
StringVector acceptableGeometry({"Vertex"});
std::vector<int> minimumCounts({3});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys({isAngle3Pt});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d angle dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d;
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d angle dimension from selection"));
return;
}
}
//build the dimension
DrawViewDimension* dim = dimensionMaker(partFeat, "Angle3Pt", references2d, references3d);
//position the Dimension text on the view
positionDimText(dim);
}
// TechDraw_LinkDimension is DEPRECATED. Use TechDraw_DimensionRepair instead.
//! link 3D geometry to Dimension(s) on a Page
//TODO: should we present all potential Dimensions from all Pages?
//===========================================================================
// TechDraw_LinkDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawLinkDimension)
CmdTechDrawLinkDimension::CmdTechDrawLinkDimension()
: Command("TechDraw_LinkDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Link Dimension to 3D Geometry");
sToolTipText = sMenuText;
sWhatsThis = "TechDraw_LinkDimension";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_LinkDimension";
}
void CmdTechDrawLinkDimension::activated(int iMsg)
{
Q_UNUSED(iMsg);
TechDraw::DrawPage* page = DrawGuiUtil::findPage(this);
if (!page) {
return;
}
bool result = _checkSelection(this, 2);
if (!result) {
return;
}
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(
nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::NoResolve);
App::DocumentObject* obj3D = nullptr;
std::vector<App::DocumentObject*> parts;
std::vector<std::string> subs;
std::vector<Gui::SelectionObject>::iterator itSel = selection.begin();
for (; itSel != selection.end(); itSel++) {
obj3D = ((*itSel).getObject());
std::vector<std::string> subList = (*itSel).getSubNames();
for (auto& s : subList) {
parts.push_back(obj3D);
subs.push_back(s);
}
}
if (!obj3D) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("There is no 3D object in your selection"));
return;
}
if (subs.empty()) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("There are no 3D Edges or Vertices in your selection"));
return;
}
// dialog to select the Dimension to link
Gui::Control().showDialog(new TaskDlgLinkDim(parts, subs, page));
page->getDocument()->recompute();//still need to recompute in Gui. why?
}
bool CmdTechDrawLinkDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
bool taskInProgress = false;
if (havePage) {
taskInProgress = Gui::Control().activeDialog();
}
return (havePage && haveView && !taskInProgress);
}
//===========================================================================
// TechDraw_ExtentGroup
//===========================================================================
DEF_STD_CMD_ACL(CmdTechDrawExtentGroup)
CmdTechDrawExtentGroup::CmdTechDrawExtentGroup()
: Command("TechDraw_ExtentGroup")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Extent Dimension");
sToolTipText = sMenuText;
sWhatsThis = "TechDraw_ExtentGroup";
sStatusTip = sToolTipText;
// eType = ForEdit;
}
void CmdTechDrawExtentGroup::activated(int iMsg)
{
// Base::Console().Message("CMD::ExtentGrp - activated(%d)\n", iMsg);
Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
if (dlg) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Task In Progress"),
QObject::tr("Close 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(QString::fromLatin1("TechDraw_HorizontalExtentDimension"));
p1->setWhatsThis(QString::fromLatin1("TechDraw_HorizontalExtentDimension"));
QAction* p2 = pcAction->addAction(QString());
p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_VerticalExtentDimension"));
p2->setObjectName(QString::fromLatin1("TechDraw_VerticalExtentDimension"));
p2->setWhatsThis(QString::fromLatin1("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()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this, false);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_HorizontalExtentDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawHorizontalExtentDimension)
CmdTechDrawHorizontalExtentDimension::CmdTechDrawHorizontalExtentDimension()
: Command("TechDraw_HorizontalExtentDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Horizontal Extent Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execExtent(this, "DistanceX");
}
bool CmdTechDrawHorizontalExtentDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this, false);
return (havePage && haveView);
}
void execExtent(Gui::Command* cmd, const std::string& dimType)
{
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);
//Define the geometric configuration required for a extent dimension
StringVector acceptableGeometry({"Edge"});
std::vector<int> minimumCounts({1});
std::vector<DimensionGeometryType> acceptableDimensionGeometrys({isMultiEdge,
isHorizontal,
isVertical,
isDiagonal,
isCircle,
isEllipse,
isBSplineCircle,
isBSpline,
isZLimited});
//what 2d geometry configuration did we receive?
DimensionGeometryType geometryRefs2d = validateDimSelection(
references2d, acceptableGeometry, minimumCounts, acceptableDimensionGeometrys);
if (geometryRefs2d == TechDraw::isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 2d extent dimension from selection"));
return;
}
//what 3d geometry configuration did we receive?
DimensionGeometryType geometryRefs3d;
if (geometryRefs2d == TechDraw::isViewReference && !references3d.empty()) {
geometryRefs3d = validateDimSelection3d(partFeat,
references3d,
acceptableGeometry,
minimumCounts,
acceptableDimensionGeometrys);
if (geometryRefs3d == isInvalid) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Incorrect Selection"),
QObject::tr("Can not make 3d extent dimension from selection"));
return;
}
}
if (references3d.empty()) {
DrawDimHelper::makeExtentDim(partFeat, dimType, references2d);
}
else {
DrawDimHelper::makeExtentDim3d(partFeat, dimType, references3d);
}
}
//===========================================================================
// TechDraw_VerticalExtentDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawVerticalExtentDimension)
CmdTechDrawVerticalExtentDimension::CmdTechDrawVerticalExtentDimension()
: Command("TechDraw_VerticalExtentDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Vertical Extent Dimension");
sToolTipText = sMenuText;
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 active task dialog and try again."));
return;
}
execExtent(this, "DistanceY");
}
bool CmdTechDrawVerticalExtentDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this, false);
return (havePage && haveView);
}
//===========================================================================
// 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 = sMenuText;
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));
}
// ReferenceVector references2d;
// ReferenceVector references3d;
// //TechDraw::DrawViewPart* partFeat =
// TechDraw::getReferencesFromSelection(references2d, references3d);
// Gui::Control().showDialog(new TaskDlgDimReference(dim, references2d, references3d));
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);
}
//NOTE: to be deprecated. revisions to the basic dimension allows it to handle
//everything that the Landmark Dimension was created to handle.
//===========================================================================
// TechDraw_LandmarkDimension
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawLandmarkDimension)
CmdTechDrawLandmarkDimension::CmdTechDrawLandmarkDimension()
: Command("TechDraw_LandmarkDimension")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert Landmark Dimension - EXPERIMENTAL");
sToolTipText = sMenuText;
sWhatsThis = "TechDraw_LandmarkDimension";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_LandmarkDimension";
}
void CmdTechDrawLandmarkDimension::activated(int iMsg)
{
Q_UNUSED(iMsg);
bool result = _checkSelection(this, 3);
if (!result) {
return;
}
const std::vector<App::DocumentObject*> objects =
getSelection().getObjectsOfType(Part::Feature::getClassTypeId());//??
if (objects.size() != 2) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Wrong selection"),
QObject::tr("Select 2 point objects and 1 View. (1)"));
return;
}
const std::vector<App::DocumentObject*> views =
getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId());
if (views.size() != 1) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("Wrong selection"),
QObject::tr("Select 2 point objects and 1 View. (2)"));
return;
}
TechDraw::DrawViewPart* dvp = static_cast<TechDraw::DrawViewPart*>(views.front());
std::vector<App::DocumentObject*> refs2d;
std::vector<std::string> subs;
subs.emplace_back("Vertex1");
subs.emplace_back("Vertex1");
TechDraw::DrawPage* page = dvp->findParentPage();
std::string parentName = dvp->getNameInDocument();
std::string PageName = page->getNameInDocument();
TechDraw::LandmarkDimension* dim = nullptr;
std::string FeatName = getUniqueObjectName("LandmarkDim");
openCommand(QT_TRANSLATE_NOOP("Command", "Create Dimension"));
doCommand(Doc,
"App.activeDocument().addObject('TechDraw::LandmarkDimension', '%s')",
FeatName.c_str());
doCommand(Doc, "App.activeDocument().%s.translateLabel('LandmarkDimension', 'LandmarkDim', '%s')",
FeatName.c_str(), FeatName.c_str());
if (objects.size() == 2) {
//what about distanceX and distanceY??
doCommand(Doc, "App.activeDocument().%s.Type = '%s'", FeatName.c_str(), "Distance");
refs2d.push_back(dvp);
refs2d.push_back(dvp);
}
// } else if (objects.size() == 3) { //not implemented yet
// doCommand(Doc, "App.activeDocument().%s.Type = '%s'", FeatName.c_str(), "Angle3Pt");
// refs2d.push_back(dvp);
// refs2d.push_back(dvp);
// refs2d.push_back(dvp);
// //subs.push_back("Vertex1");
// //subs.push_back("Vertex1");
// //subs.push_back("Vertex1");
// }
dim = dynamic_cast<TechDraw::LandmarkDimension*>(getDocument()->getObject(FeatName.c_str()));
if (!dim) {
throw Base::TypeError("CmdTechDrawLandmarkDimension - dim not found\n");
}
dim->References2D.setValues(refs2d, subs);
dim->References3D.setValues(objects, subs);
doCommand(Doc,
"App.activeDocument().%s.addView(App.activeDocument().%s)",
PageName.c_str(),
FeatName.c_str());
commitCommand();
// Touch the parent feature so the dimension in tree view appears as a child
dvp->touch(true);
dim->recomputeFeature();
}
bool CmdTechDrawLandmarkDimension::isActive()
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//------------------------------------------------------------------------------
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 CmdTechDrawExtentGroup());
rcCmdMgr.addCommand(new CmdTechDrawVerticalExtentDimension());
rcCmdMgr.addCommand(new CmdTechDrawHorizontalExtentDimension());
rcCmdMgr.addCommand(new CmdTechDrawLinkDimension());
rcCmdMgr.addCommand(new CmdTechDrawLandmarkDimension());
rcCmdMgr.addCommand(new CmdTechDrawDimensionRepair());
rcCmdMgr.addCommand(new CmdTechDrawCompDimensionTools());
}
//------------------------------------------------------------------------------
//Common code to build a dimension feature
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;
}