diff --git a/src/Mod/PartDesign/App/Body.cpp b/src/Mod/PartDesign/App/Body.cpp index 339f55e4b..9a09d824d 100644 --- a/src/Mod/PartDesign/App/Body.cpp +++ b/src/Mod/PartDesign/App/Body.cpp @@ -230,51 +230,64 @@ const bool Body::isAllowed(const App::DocumentObject* f) ); } + void Body::addFeature(App::DocumentObject *feature) { - // Set the BaseFeature property - if (feature->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId())) { - App::DocumentObject* prevSolidFeature = getPrevSolidFeature(NULL, true); - if (prevSolidFeature != NULL) - // Set BaseFeature property to previous feature (this might be the Tip feature) - static_cast(feature)->BaseFeature.setValue(prevSolidFeature); + insertFeature (feature, Tip.getValue(), /*after = */ true); + + // Move the Tip + Tip.setValue (feature); +} + + +void Body::insertFeature(App::DocumentObject* feature, App::DocumentObject* target, bool after) +{ + // Check if the after feature belongs to the body + if (target && !hasFeature (target)) { + throw Base::Exception("Body: the feature we should insert relative to is not part of that body"); } + std::vector model = Model.getValues(); + std::vector::iterator insertInto; + + // Find out the position there to insert the feature + if (!target) { + if (after) { + insertInto = model.begin(); + } else { + insertInto = model.end(); + } + } else { + std::vector::iterator targetIt = std::find (model.begin(), model.end(), target); + assert (targetIt != model.end()); + if (after) { + insertInto = targetIt + 1; + } else { + insertInto = targetIt; + } + } + + // Insert the new feature after the given + model.insert (insertInto, feature); + + Model.setValues (model); + + // Set the BaseFeature property if (Body::isSolidFeature(feature)) { + // Set BaseFeature property to previous feature (this might be the Tip feature) + App::DocumentObject* prevSolidFeature = getPrevSolidFeature(feature, false); + if (prevSolidFeature) + static_cast(feature)->BaseFeature.setValue(prevSolidFeature); + // Reroute the next solid feature's BaseFeature property to this feature - App::DocumentObject* nextSolidFeature = getNextSolidFeature(NULL, false); - if (nextSolidFeature != NULL) + App::DocumentObject* nextSolidFeature = getNextSolidFeature(feature, false); + if (nextSolidFeature) static_cast(nextSolidFeature)->BaseFeature.setValue(feature); } - // Insert the new feature after the current Tip feature - App::DocumentObject* tipFeature = Tip.getValue(); - std::vector model = Model.getValues(); - if (tipFeature == NULL) { - if (model.empty()) - // First feature in the body - model.push_back(feature); - else - // Insert feature as before all other features in the body - model.insert(model.begin(), feature); - } else { - // Insert after Tip - std::vector::iterator it = std::find(model.begin(), model.end(), tipFeature); - if (it == model.end()) - throw Base::Exception("Body: Tip is not contained in model"); - - it++; - if (it == model.end()) - model.push_back(feature); - else - model.insert(it, feature); - } - Model.setValues(model); - - // Move the Tip - Tip.setValue(feature); } + void Body::removeFeature(App::DocumentObject* feature) { // This method must be called BEFORE the feature is removed from the Document! @@ -328,6 +341,7 @@ void Body::removeFeature(App::DocumentObject* feature) } + App::DocumentObjectExecReturn *Body::execute(void) { /* diff --git a/src/Mod/PartDesign/App/Body.h b/src/Mod/PartDesign/App/Body.h index a4d8fde8d..a28922c8e 100644 --- a/src/Mod/PartDesign/App/Body.h +++ b/src/Mod/PartDesign/App/Body.h @@ -81,9 +81,22 @@ public: /// Add the feature into the body at the current insert point (Tip feature) void addFeature(App::DocumentObject* feature); + /** + * Insert the feature into the body after the given feature. + * + * @param feature The feature to insert into the body + * @param target The feature relative which one should be inserted the given. + * If target is NULL than insert into the end if where is InsertBefore + * and into the begin if where is InsertAfter. + * @param after if true insert the feature after the target. Default is false. + * + * @note the methode doesn't modifies the Tip unlike addFeature() + */ + void insertFeature(App::DocumentObject* feature, App::DocumentObject* target, bool after=false); + /// Remove the feature from the body void removeFeature(App::DocumentObject* feature); - + /// Checks if the given document object is a feaure of this body bool isFeature(App::DocumentObject* feature); diff --git a/src/Mod/PartDesign/App/BodyPy.xml b/src/Mod/PartDesign/App/BodyPy.xml index 9d86dd0cb..7bc4af422 100644 --- a/src/Mod/PartDesign/App/BodyPy.xml +++ b/src/Mod/PartDesign/App/BodyPy.xml @@ -23,5 +23,20 @@ removeFeature(feat) - Remove the given feature from the Body + + + insertFeatureAfter(feature, target, after=False) + Insert the feature into the body after the given feature. + + @param feature The feature to insert into the body + @param target The feature relative which one should be inserted the given. + If target is NULL than insert into the end if where is InsertBefore + and into the begin if where is InsertAfter. + @param after if true insert the feature after the target. Default is false. + + @note the methode doesn't modifies the Tip unlike addFeature() + + + diff --git a/src/Mod/PartDesign/App/BodyPyImp.cpp b/src/Mod/PartDesign/App/BodyPyImp.cpp index 195b88fd4..11a3fd871 100644 --- a/src/Mod/PartDesign/App/BodyPyImp.cpp +++ b/src/Mod/PartDesign/App/BodyPyImp.cpp @@ -1,6 +1,8 @@ #include "PreCompiled.h" +#include + #include "Mod/Part/App/Part2DObject.h" #include "Mod/PartDesign/App/Body.h" @@ -40,6 +42,7 @@ PyObject* BodyPy::addFeature(PyObject *args) PyErr_SetString(PyExc_SystemError, "Only PartDesign features, datum features and sketches can be inserted into a Body"); return 0; } + Body* body = this->getBodyPtr(); try { @@ -52,6 +55,45 @@ PyObject* BodyPy::addFeature(PyObject *args) Py_Return; } +PyObject* BodyPy::insertFeature(PyObject *args) +{ + PyObject* featurePy; + PyObject* targetPy; + PyObject* afterPy = 0; + if (!PyArg_ParseTuple(args, "O!O|O", &(App::DocumentObjectPy::Type), &featurePy, &targetPy, &afterPy)) { + return 0; + } + + App::DocumentObject* feature = static_cast(featurePy)->getDocumentObjectPtr(); + App::DocumentObject* target = static_cast(targetPy)->getDocumentObjectPtr(); + int after = 0; + + if (!Body::isAllowed(feature)) { + PyErr_SetString(PyExc_SystemError, "Only PartDesign features, datum features and sketches can be inserted into a Body"); + return 0; + } + + if (afterPy) { + after = PyObject_IsTrue(afterPy); + if ( after == -1) { + // Note: shouldn't happen + PyErr_SetString(PyExc_ValueError, "The after parameter should be of boolean type"); + return 0; + } + } + + Body* body = this->getBodyPtr(); + + try { + body->insertFeature(feature, target, after); + } catch (Base::Exception& e) { + PyErr_SetString(PyExc_SystemError, e.what()); + return 0; + } + + Py_Return; +} + PyObject* BodyPy::removeFeature(PyObject *args) { PyObject* featurePy;