From 526cc024ad1e73a121f26f11e2dd7119efbc2aa6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 31 May 2024 11:40:30 +0200 Subject: [PATCH] Part: Add AttacherEngine of type PropertyEnumeration This is added to conveniently change the attacher type of a Part object. Hint: A new property is used to avoid to break project files when opening it with an older version. See also forum thread: https://forum.freecad.org/viewtopic.php?t=87891 --- src/Mod/Part/App/AttachExtension.cpp | 68 +++++++++++++++++++++- src/Mod/Part/App/AttachExtension.h | 1 + tests/src/Mod/Part/App/AttachExtension.cpp | 42 +++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/Mod/Part/App/AttachExtension.cpp b/src/Mod/Part/App/AttachExtension.cpp index 53ddf40fa6..12f7a99327 100644 --- a/src/Mod/Part/App/AttachExtension.cpp +++ b/src/Mod/Part/App/AttachExtension.cpp @@ -32,6 +32,59 @@ using namespace Part; using namespace Attacher; +namespace +{ + std::vector EngineEnums = {"Engine 3D", + "Engine Plane", + "Engine Line", + "Engine Point"}; + + const char* enumToClass(const char* mode) + { + if (EngineEnums.at(0) == mode) { + return "Attacher::AttachEngine3D"; + } + if (EngineEnums.at(1) == mode) { + return "Attacher::AttachEnginePlane"; + } + if (EngineEnums.at(2) == mode) { + return "Attacher::AttachEngineLine"; + } + if (EngineEnums.at(3) == mode) { + return "Attacher::AttachEnginePoint"; + } + + return "Attacher::AttachEngine3D"; + } + + const char* classToEnum(const char* type) + { + if (strcmp(type, "Attacher::AttachEngine3D") == 0) { + return EngineEnums.at(0).c_str(); + } + if (strcmp(type, "Attacher::AttachEnginePlane") == 0) { + return EngineEnums.at(1).c_str(); + } + if (strcmp(type, "Attacher::AttachEngineLine") == 0) { + return EngineEnums.at(2).c_str(); + } + if (strcmp(type, "Attacher::AttachEnginePoint") == 0) { + return EngineEnums.at(3).c_str(); + } + + return EngineEnums.at(0).c_str(); + } + + void restoreAttacherEngine(AttachExtension* self) + { + const char* mode = enumToClass(self->AttacherEngine.getValueAsString()); + const char* type = self->AttacherType.getValue(); + if (strcmp(mode, type) != 0) { + self->AttacherEngine.setValue(classToEnum(type)); + } + } +} + EXTENSION_PROPERTY_SOURCE(Part::AttachExtension, App::DocumentObjectExtension) #ifdef FC_USE_TNP_FIX @@ -41,9 +94,15 @@ AttachExtension::AttachExtension() EXTENSION_ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment", - (App::PropertyType)(App::Prop_None), + (App::PropertyType)(App::Prop_ReadOnly | App::Prop_Hidden), "Class name of attach engine object driving the attachment."); - this->AttacherType.setStatus(App::Property::Status::Hidden, true); + + EXTENSION_ADD_PROPERTY_TYPE(AttacherEngine, + (0L), + "Attachment", + (App::PropertyType)(App::Prop_None), + "Attach engine object driving the attachment."); + AttacherEngine.setEnums(EngineEnums); EXTENSION_ADD_PROPERTY_TYPE( Support, @@ -354,6 +413,9 @@ void AttachExtension::extensionOnChanged(const App::Property* prop) AttachmentSupport.Paste(Support); } } + else if (prop == &AttacherEngine) { + AttacherType.setValue(enumToClass(AttacherEngine.getValueAsString())); + } else if (_props.matchProperty(prop)) { if (prop == &AttachmentSupport) { Base::ObjectStatusLocker guard( @@ -407,6 +469,8 @@ void AttachExtension::onExtendedDocumentRestored() } _active = -1; updatePropertyStatus(isAttacherActive()); + + restoreAttacherEngine(this); } catch (Base::Exception&) { } diff --git a/src/Mod/Part/App/AttachExtension.h b/src/Mod/Part/App/AttachExtension.h index e8f9df2348..87069bdf28 100644 --- a/src/Mod/Part/App/AttachExtension.h +++ b/src/Mod/Part/App/AttachExtension.h @@ -87,6 +87,7 @@ public: Attacher::AttachEngine& attacher(bool base = false) const; App::PropertyString AttacherType; + App::PropertyEnumeration AttacherEngine; App::PropertyLinkSubList Support; // deprecated, leave here for backward compatibility App::PropertyLinkSubList AttachmentSupport; App::PropertyEnumeration MapMode; // see AttachEngine::eMapMode diff --git a/tests/src/Mod/Part/App/AttachExtension.cpp b/tests/src/Mod/Part/App/AttachExtension.cpp index 0123831b9e..89afe01be1 100644 --- a/tests/src/Mod/Part/App/AttachExtension.cpp +++ b/tests/src/Mod/Part/App/AttachExtension.cpp @@ -54,3 +54,45 @@ TEST_F(AttachExtensionTest, testPlanePlane) getDocument()->recompute(); EXPECT_TRUE(true); } + +TEST_F(AttachExtensionTest, testAttacherEngineType) +{ + auto plane = dynamic_cast(getDocument()->addObject("Part::Plane", "Plane")); + EXPECT_STREQ(plane->AttacherType.getValue(), "Attacher::AttachEngine3D"); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine 3D"); + + plane->AttacherEngine.setValue(1L); + EXPECT_STREQ(plane->AttacherType.getValue(), "Attacher::AttachEnginePlane"); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine Plane"); + + plane->AttacherEngine.setValue(2L); + EXPECT_STREQ(plane->AttacherType.getValue(), "Attacher::AttachEngineLine"); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine Line"); + + plane->AttacherEngine.setValue(3L); + EXPECT_STREQ(plane->AttacherType.getValue(), "Attacher::AttachEnginePoint"); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine Point"); +} + +TEST_F(AttachExtensionTest, testAttacherTypeEngine) +{ + auto plane = dynamic_cast(getDocument()->addObject("Part::Plane", "Plane")); + EXPECT_STREQ(plane->AttacherType.getValue(), "Attacher::AttachEngine3D"); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine 3D"); + + plane->AttacherType.setValue("Attacher::AttachEnginePlane"); + plane->onExtendedDocumentRestored(); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine Plane"); + + plane->AttacherType.setValue("Attacher::AttachEngineLine"); + plane->onExtendedDocumentRestored(); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine Line"); + + plane->AttacherType.setValue("Attacher::AttachEnginePoint"); + plane->onExtendedDocumentRestored(); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine Point"); + + plane->AttacherType.setValue("Attacher::AttachEngine3D"); + plane->onExtendedDocumentRestored(); + EXPECT_STREQ(plane->AttacherEngine.getValueAsString(), "Engine 3D"); +}