diff --git a/src/Mod/Measure/App/MeasureAngle.cpp b/src/Mod/Measure/App/MeasureAngle.cpp index 1ba621f92b32b..6873c7ee8bfe3 100644 --- a/src/Mod/Measure/App/MeasureAngle.cpp +++ b/src/Mod/Measure/App/MeasureAngle.cpp @@ -254,7 +254,7 @@ void MeasureAngle::onChanged(const App::Property* prop) //! Return the object we are measuring //! used by the viewprovider in determining visibility -App::DocumentObject* MeasureAngle::getSubject() const +std::vector MeasureAngle::getSubject() const { - return Element1.getValue(); + return {Element1.getValue()}; } diff --git a/src/Mod/Measure/App/MeasureAngle.h b/src/Mod/Measure/App/MeasureAngle.h index 9a2f32b4482d4..bc4d47954b64d 100644 --- a/src/Mod/Measure/App/MeasureAngle.h +++ b/src/Mod/Measure/App/MeasureAngle.h @@ -77,7 +77,7 @@ class MeasureExport MeasureAngle : public Measure::MeasureBaseExtendableAngle;} // Return the object we are measuring - App::DocumentObject* getSubject() const override; + std::vector getSubject() const override; static bool getVec(App::DocumentObject& ob, std::string& subName, Base::Vector3d& vecOut); diff --git a/src/Mod/Measure/App/MeasureArea.cpp b/src/Mod/Measure/App/MeasureArea.cpp index 92678a719ecb5..f2d8a6210e1b0 100644 --- a/src/Mod/Measure/App/MeasureArea.cpp +++ b/src/Mod/Measure/App/MeasureArea.cpp @@ -182,11 +182,7 @@ Base::Placement MeasureArea::getPlacement() { //! Return the object we are measuring //! used by the viewprovider in determining visibility -App::DocumentObject* MeasureArea::getSubject() const +std::vector MeasureArea::getSubject() const { - auto elements = Elements.getValues(); - if (elements.empty()) { - return nullptr; - } - return Elements.getValues().front(); + return Elements.getValues(); } diff --git a/src/Mod/Measure/App/MeasureArea.h b/src/Mod/Measure/App/MeasureArea.h index 6c7e48bf1ec75..fb4a53b2f2fa5 100644 --- a/src/Mod/Measure/App/MeasureArea.h +++ b/src/Mod/Measure/App/MeasureArea.h @@ -83,7 +83,7 @@ class MeasureExport MeasureArea : public Measure::MeasureBaseExtendable getSubject() const override; private: diff --git a/src/Mod/Measure/App/MeasureBase.h b/src/Mod/Measure/App/MeasureBase.h index 567b5f4edd9e7..3488c278b06e4 100644 --- a/src/Mod/Measure/App/MeasureBase.h +++ b/src/Mod/Measure/App/MeasureBase.h @@ -56,7 +56,8 @@ class AppExport MeasureBase : public App::DocumentObject virtual QString getResultString(); virtual Base::Placement getPlacement() {return Base::Placement();} - virtual App::DocumentObject* getSubject() const = 0; + virtual std::vector getSubject() const = 0; + protected: void onDocumentRestored() override; }; diff --git a/src/Mod/Measure/App/MeasureDistance.cpp b/src/Mod/Measure/App/MeasureDistance.cpp index 31bb3291ced80..378465595f303 100644 --- a/src/Mod/Measure/App/MeasureDistance.cpp +++ b/src/Mod/Measure/App/MeasureDistance.cpp @@ -219,8 +219,8 @@ void MeasureDistance::onChanged(const App::Property* prop) //! Return the object we are measuring //! used by the viewprovider in determining visibility -App::DocumentObject* MeasureDistance::getSubject() const +std::vector MeasureDistance::getSubject() const { - return Element1.getValue(); + return {Element1.getValue()}; } diff --git a/src/Mod/Measure/App/MeasureDistance.h b/src/Mod/Measure/App/MeasureDistance.h index 974f7f06aa128..f07dfc0d687b6 100644 --- a/src/Mod/Measure/App/MeasureDistance.h +++ b/src/Mod/Measure/App/MeasureDistance.h @@ -82,7 +82,7 @@ class MeasureExport MeasureDistance : public Measure::MeasureBaseExtendable getSubject() const override; private: diff --git a/src/Mod/Measure/App/MeasureLength.cpp b/src/Mod/Measure/App/MeasureLength.cpp index dc0f2e497aecf..d3f1ee63a6c0a 100644 --- a/src/Mod/Measure/App/MeasureLength.cpp +++ b/src/Mod/Measure/App/MeasureLength.cpp @@ -182,12 +182,8 @@ Base::Placement MeasureLength::getPlacement() { //! Return the object we are measuring //! used by the viewprovider in determining visibility -App::DocumentObject* MeasureLength::getSubject() const +std::vector MeasureLength::getSubject() const { - auto elements = Elements.getValues(); - if (elements.empty()) { - return nullptr; - } - return Elements.getValues().front(); + return Elements.getValues(); } diff --git a/src/Mod/Measure/App/MeasureLength.h b/src/Mod/Measure/App/MeasureLength.h index 340deaeca112b..160a005ba411a 100644 --- a/src/Mod/Measure/App/MeasureLength.h +++ b/src/Mod/Measure/App/MeasureLength.h @@ -83,7 +83,7 @@ class MeasureExport MeasureLength : public Measure::MeasureBaseExtendable getSubject() const override; private: diff --git a/src/Mod/Measure/App/MeasurePosition.cpp b/src/Mod/Measure/App/MeasurePosition.cpp index 89c9f17360c0c..e3923075a7deb 100644 --- a/src/Mod/Measure/App/MeasurePosition.cpp +++ b/src/Mod/Measure/App/MeasurePosition.cpp @@ -131,7 +131,6 @@ void MeasurePosition::recalculatePosition() std::string obName = object->getNameInDocument(); auto result = handler(&obName, &subElement); Position.setValue(result); - return; } void MeasurePosition::onChanged(const App::Property* prop) @@ -150,18 +149,24 @@ void MeasurePosition::onChanged(const App::Property* prop) QString MeasurePosition::getResultString() { App::Property* prop = this->getResultProp(); if (prop == nullptr) { - return QString(); + return {}; } Base::Vector3d value = Position.getValue(); QString unit = Position.getUnit().getString(); int precision = 2; QString text; - QTextStream(&text) + #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QTextStream(&text) + << "X: " << QString::number(value.x, 'f', precision) << " " << unit << endl + << "Y: " << QString::number(value.y, 'f', precision) << " " << unit << endl + << "Z: " << QString::number(value.z, 'f', precision) << " " << unit; + #else + QTextStream(&text) << "X: " << QString::number(value.x, 'f', precision) << " " << unit << Qt::endl << "Y: " << QString::number(value.y, 'f', precision) << " " << unit << Qt::endl << "Z: " << QString::number(value.z, 'f', precision) << " " << unit; - + #endif return text; } @@ -175,7 +180,7 @@ Base::Placement MeasurePosition::getPlacement() { //! Return the object we are measuring //! used by the viewprovider in determining visibility -App::DocumentObject* MeasurePosition::getSubject() const +std::vector MeasurePosition::getSubject() const { - return Element.getValue(); + return {Element.getValue()}; } diff --git a/src/Mod/Measure/App/MeasurePosition.h b/src/Mod/Measure/App/MeasurePosition.h index 8f42e30da68f4..9f85c32068579 100644 --- a/src/Mod/Measure/App/MeasurePosition.h +++ b/src/Mod/Measure/App/MeasurePosition.h @@ -69,7 +69,7 @@ class MeasureExport MeasurePosition : public Measure::MeasureBaseExtendable getSubject() const override; private: diff --git a/src/Mod/Measure/App/MeasureRadius.cpp b/src/Mod/Measure/App/MeasureRadius.cpp index 43185d4a02efa..82ba8ed885f3e 100644 --- a/src/Mod/Measure/App/MeasureRadius.cpp +++ b/src/Mod/Measure/App/MeasureRadius.cpp @@ -210,7 +210,7 @@ MeasureRadiusInfo MeasureRadius::getMeasureInfoFirst() const //! Return the object we are measuring //! used by the viewprovider in determining visibility -App::DocumentObject* MeasureRadius::getSubject() const +std::vector MeasureRadius::getSubject() const { - return Element.getValue(); + return {Element.getValue()}; } diff --git a/src/Mod/Measure/App/MeasureRadius.h b/src/Mod/Measure/App/MeasureRadius.h index b99bef2c3d433..952e5b0a1db05 100644 --- a/src/Mod/Measure/App/MeasureRadius.h +++ b/src/Mod/Measure/App/MeasureRadius.h @@ -89,7 +89,7 @@ class MeasureExport MeasureRadius : public Measure::MeasureBaseExtendable getSubject() const override; private: diff --git a/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp b/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp index d535c0c3edea9..40bf12638981d 100644 --- a/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp +++ b/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp @@ -229,6 +229,22 @@ void ViewProviderMeasureBase::connectToSubject(App::DocumentObject* subject) subject->signalChanged.connect(bndVisibility); } +//! connect to the subject to receive visibility updates +void ViewProviderMeasureBase::connectToSubject(std::vector subject) +{ + if (subject.empty()) { + return; + } + + //NOLINTBEGIN + auto bndVisibility = boost::bind(&ViewProviderMeasureBase::onSubjectVisibilityChanged, this, bp::_1, bp::_2); + //NOLINTEND + + // TODO: should we connect to all the subject objects when there is >1? + auto proxy = subject.front(); + proxy->signalChanged.connect(bndVisibility); +} + //! retrive the feature Measure::MeasureBase* ViewProviderMeasureBase::getMeasureObject() @@ -248,41 +264,54 @@ Measure::MeasureBase* ViewProviderMeasureBase::getMeasureObject() //! an example of an elementDirection would be the vector from the start of a line to the end. Base::Vector3d ViewProviderMeasureBase::getTextDirection(Base::Vector3d elementDirection, double tolerance) { + // TODO: this can fail if the active view is not a 3d view (spreadsheet, techdraw page) and something causes a measure to try to update + // we need to search throught the mdi views for a 3d view and take the direction from it (or decide that if the active view is not 3d, + // assume we are looking from the front). + Base::Vector3d viewDirection; + Base::Vector3d upDirection; auto view = dynamic_cast(Gui::Application::Instance->activeDocument()->getActiveView()); - // if (!view) { - // // Measure doesn't work with this kind of active view. Might be dependency graph, might be TechDraw, or ???? - // // i don't know if this can even happen. - // throw Base::RuntimeError("Measure doesn't work with this kind of active view."); - // } - Gui::View3DInventorViewer* viewer = view->getViewer(); - Base::Vector3d viewDirection = toVector3d(viewer->getViewDirection()).Normalize(); + if (view) { + Gui::View3DInventorViewer* viewer = view->getViewer(); + viewDirection = toVector3d(viewer->getViewDirection()).Normalize(); + upDirection = toVector3d(viewer->getUpDirection()).Normalize(); + // Measure doesn't work with this kind of active view. Might be dependency graph, might be TechDraw, or ???? + //throw Base::RuntimeError("Measure doesn't work with this kind of active view."); + } else { + viewDirection = Base::Vector3d(0.0, 1.0, 0.0); + upDirection = Base::Vector3d(0.0, 0.0, 1.0); + } + Base::Vector3d textDirection = elementDirection.Cross(viewDirection); if (textDirection.Length() < tolerance) { // either elementDirection and viewDirection are parallel or one of them is null. - viewDirection = toVector3d(viewer->getUpDirection()).Normalize(); - textDirection = elementDirection.Cross(viewDirection); + textDirection = elementDirection.Cross(upDirection); } return textDirection.Normalize(); } -//! true if the subject of this measurement is visible + +//! true if the subject of this measurement is visible. For Measures that have multiple object subject, +//! all of the subjects must be visible. bool ViewProviderMeasureBase::isSubjectVisible() { // we need these things to proceed if (!getMeasureObject() || - !getMeasureObject()->getSubject() || + getMeasureObject()->getSubject().empty() || !Gui::Application::Instance->getDocument(getMeasureObject()->getDocument()) ) { return false; } auto guiDoc = Gui::Application::Instance->getDocument(getMeasureObject()->getDocument()); - Gui::ViewProvider* vp = guiDoc->getViewProvider(getMeasureObject()->getSubject()); - if (vp) { - return vp->isVisible(); + for (auto & obj : getMeasureObject()->getSubject()) { + Gui::ViewProvider* vp = guiDoc->getViewProvider(obj); + if (!vp || !vp->isVisible()) { + return false; + } } - return false; + // all of the subject objects are visible + return true; } @@ -292,11 +321,12 @@ void ViewProviderMeasureBase::onSubjectVisibilityChanged(const App::DocumentObje { std::string propName = prop.getName(); if (propName == "Visibility") { - if (docObj.Visibility.getValue()) { - // show only if subject is visible - setVisible(true); - } else { + if (!docObj.Visibility.getValue()) { + // show ourselves only if subject is visible setVisible(false); + } else { + // here, we don't know if we should be visible or not, so we have to check the whole subject + setVisible(isSubjectVisible()); } } } diff --git a/src/Mod/Measure/Gui/ViewProviderMeasureBase.h b/src/Mod/Measure/Gui/ViewProviderMeasureBase.h index db577ac5d4eba..c86436d9fbd70 100644 --- a/src/Mod/Measure/Gui/ViewProviderMeasureBase.h +++ b/src/Mod/Measure/Gui/ViewProviderMeasureBase.h @@ -95,7 +95,8 @@ class MeasureGuiExport ViewProviderMeasureBase :public Gui::ViewProviderDocument using Connection = boost::signals2::scoped_connection; Connection connectVisibilityChanged; void onSubjectVisibilityChanged(const App::DocumentObject& docObj, const App::Property& prop); - void connectToSubject(App::DocumentObject* subject); + void connectToSubject(App::DocumentObject* subject); + void connectToSubject(std::vector subject); protected: void onChanged(const App::Property* prop) override;