More bug fixes for Body insertion/deletion of features

This commit is contained in:
jrheinlaender 2013-04-12 16:16:34 +04:30 committed by Stefan Tröger
parent ee47c53339
commit 63f782d8f0
9 changed files with 125 additions and 98 deletions

View File

@ -50,25 +50,55 @@ Body::Body()
ADD_PROPERTY(IsActive,(0));
}
/*
// Note: The following code will catch Python Document::removeObject() modifications. If the object removed is
// a member of the Body::Model, then it will be automatically removed from the Model property which triggers the
// following two methods
// But since we require the Python user to call both Document::addObject() and Body::addFeature(), we should
// also require calling both Document::removeObject and Body::removeFeature() in order to be consistent
void Body::onBeforeChange(const App::Property *prop)
{
// Remember the feature before the current Tip. If the Tip is already at the first feature, remember the next feature
if (prop == &Model) {
std::vector<App::DocumentObject*> features = Model.getValues();
if (features.empty()) {
rememberTip = NULL;
} else {
std::vector<App::DocumentObject*>::iterator it = std::find(features.begin(), features.end(), Tip.getValue());
if (it == features.begin()) {
it++;
if (it == features.end())
rememberTip = NULL;
else
rememberTip = *it;
} else {
it--;
rememberTip = *it;
}
}
}
return Part::Feature::onBeforeChange(prop);
}
void Body::onChanged(const App::Property *prop)
{
Base::Console().Error("Checking Body '%s' for sanity\n", getNameInDocument());
App::DocumentObject* tip = Tip.getValue();
Base::Console().Error(" Tip: %s\n", (tip == NULL) ? "None" : tip->getNameInDocument());
std::vector<App::DocumentObject*> model = Model.getValues();
Base::Console().Error(" Model:\n");
for (std::vector<App::DocumentObject*>::const_iterator m = model.begin(); m != model.end(); m++) {
Base::Console().Error(" %s", (*m)->getNameInDocument());
if ((*m)->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) {
App::DocumentObject* baseFeature = static_cast<PartDesign::SketchBased*>(*m)->BaseFeature.getValue();
Base::Console().Error(", Base: %s\n", baseFeature == NULL ? "None" : baseFeature->getNameInDocument());
if (prop == &Model) {
std::vector<App::DocumentObject*> features = Model.getValues();
if (features.empty()) {
Tip.setValue(NULL);
} else {
Base::Console().Error("\n");
std::vector<App::DocumentObject*>::iterator it = std::find(features.begin(), features.end(), Tip.getValue());
if (it == features.end()) {
// Tip feature was deleted
Tip.setValue(rememberTip);
}
}
}
return Part::Feature::onChanged(prop);
}
*/
short Body::mustExecute() const
{
@ -189,7 +219,7 @@ Body* Body::findBodyOf(const App::DocumentObject* f)
return NULL;
}
void Body::insertFeature(App::DocumentObject *feature)
void Body::addFeature(App::DocumentObject *feature)
{
// Set the BaseFeature property
// Note: This is not strictly necessary for Datum features
@ -236,6 +266,8 @@ void Body::insertFeature(App::DocumentObject *feature)
void Body::removeFeature(App::DocumentObject* feature)
{
// This method must be called BEFORE the feature is removed from the Document!
if (isSolidFeature(feature)) {
// This is a solid feature
// If the next feature is solid, reroute its BaseFeature property to the previous solid feature
@ -250,10 +282,11 @@ void Body::removeFeature(App::DocumentObject* feature)
}
}
// Adjust Tip feature if it is pointing to the deleted object
App::DocumentObject* tipFeature = Tip.getValue();
std::vector<App::DocumentObject*> model = Model.getValues();
std::vector<App::DocumentObject*>::iterator it = std::find(model.begin(), model.end(), feature);
// Adjust Tip feature if it is pointing to the deleted object
App::DocumentObject* tipFeature = Tip.getValue();
if (tipFeature == feature) {
// Set the Tip to the previous feature if possible, otherwise to the next feature
std::vector<App::DocumentObject*>::const_iterator prev = it, next = it;
@ -270,7 +303,11 @@ void Body::removeFeature(App::DocumentObject* feature)
Tip.setValue(NULL);
}
} else {
Tip.setValue(NULL);
next++;
if (next != model.end())
Tip.setValue(*next);
else
Tip.setValue(NULL);
}
}
@ -281,6 +318,22 @@ void Body::removeFeature(App::DocumentObject* feature)
App::DocumentObjectExecReturn *Body::execute(void)
{
Base::Console().Error("Checking Body '%s' for sanity\n", getNameInDocument());
App::DocumentObject* tip = Tip.getValue();
Base::Console().Error(" Tip: %s\n", (tip == NULL) ? "None" : tip->getNameInDocument());
std::vector<App::DocumentObject*> model = Model.getValues();
Base::Console().Error(" Model:\n");
for (std::vector<App::DocumentObject*>::const_iterator m = model.begin(); m != model.end(); m++) {
if (*m == NULL) continue;
Base::Console().Error(" %s", (*m)->getNameInDocument());
if ((*m)->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) {
App::DocumentObject* baseFeature = static_cast<PartDesign::SketchBased*>(*m)->BaseFeature.getValue();
Base::Console().Error(", Base: %s\n", baseFeature == NULL ? "None" : baseFeature->getNameInDocument());
} else {
Base::Console().Error("\n");
}
}
const Part::TopoShape& TipShape = getTipShape();
if (TipShape._Shape.IsNull())

View File

@ -48,9 +48,7 @@ public:
//@{
/// recalculate the feature
App::DocumentObjectExecReturn *execute(void);
short mustExecute() const;
/// Just for debugging, remove when Body functionality is stable
void onChanged(const App::Property* prop);
short mustExecute() const;
/// returns the type name of the view provider
const char* getViewProviderName(void) const {
return "PartDesignGui::ViewProviderBody";
@ -83,8 +81,8 @@ public:
/// Return true if the feature is located after the current Tip feature
const bool isAfterTip(const App::DocumentObject *f);
/// Insert the feature into the body at the current insert point (Tip feature)
void insertFeature(App::DocumentObject* feature);
/// Add the feature into the body at the current insert point (Tip feature)
void addFeature(App::DocumentObject* feature);
/// Remove the feature from the body
void removeFeature(App::DocumentObject* feature);
@ -102,7 +100,8 @@ public:
PyObject *getPyObject(void);
private:
App::DocumentObject* rememberTip;
};
} //namespace PartDesign

View File

@ -13,9 +13,9 @@
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>PartDesign body class</UserDocu>
</Documentation>
<Methode Name="insertFeature">
<Methode Name="addFeature">
<Documentation>
<UserDocu>insertFeature(feat) - Insert the given feature after the current Tip feature</UserDocu>
<UserDocu>addFeature(feat) - Add the given feature after the current Tip feature</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeFeature">

View File

@ -29,7 +29,7 @@ int BodyPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
return 0;
}
PyObject* BodyPy::insertFeature(PyObject *args)
PyObject* BodyPy::addFeature(PyObject *args)
{
PyObject* featurePy;
if (!PyArg_ParseTuple(args, "O!", &(Part::PartFeaturePy::Type), &featurePy))
@ -45,7 +45,7 @@ PyObject* BodyPy::insertFeature(PyObject *args)
Body* body = this->getBodyPtr();
try {
body->insertFeature(feature);
body->addFeature(feature);
} catch (Base::Exception& e) {
PyErr_SetString(PyExc_SystemError, e.what());
return 0;

View File

@ -280,7 +280,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
openCommand("Create a Sketch on Face");
doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),supportString.c_str());
doCommand(Doc,"App.activeDocument().%s.insertFeature(App.activeDocument().%s)",
doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), FeatName.c_str());
doCommand(Gui,"App.activeDocument().recompute()"); // recompute the sketch placement based on its support
//doCommand(Gui,"Gui.activeDocument().activeView().setCamera('%s')",cam.c_str());
@ -354,7 +354,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),supportString.c_str());
doCommand(Doc,"App.activeDocument().%s.Placement = App.Placement(App.Vector(%f,%f,%f),App.Rotation(%f,%f,%f,%f))",FeatName.c_str(),p.x,p.y,p.z,r[0],r[1],r[2],r[3]);
doCommand(Doc,"App.activeDocument().%s.insertFeature(App.activeDocument().%s)",
doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), FeatName.c_str());
//doCommand(Gui,"Gui.activeDocument().activeView().setCamera('%s')",cam.c_str());
doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str());
@ -478,7 +478,7 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which, Part::Part2
which.c_str(), FeatName.c_str());
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.Sketch = App.activeDocument().%s",
FeatName.c_str(), sketch->getNameInDocument());
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.insertFeature(App.activeDocument().%s)",
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
pcActiveBody->getNameInDocument(), FeatName.c_str());
}

View File

@ -331,15 +331,22 @@ bool TaskDlgGrooveParameters::reject()
// get the support and Sketch
PartDesign::Groove* pcGroove = static_cast<PartDesign::Groove*>(GrooveView->getObject());
Sketcher::SketchObject *pcSketch = 0;
App::DocumentObject *pcSupport = 0;
if (pcGroove->Sketch.getValue()) {
pcSketch = static_cast<Sketcher::SketchObject*>(pcGroove->Sketch.getValue());
pcSupport = pcSketch->Support.getValue();
}
// role back the done things
Gui::Command::abortCommand();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()");
// if abort command deleted the object the support is visible again
if (!Gui::Application::Instance->getViewProvider(pcGroove)) {
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
Gui::Application::Instance->getViewProvider(pcSketch)->show();
}
// Body housekeeping
if (ActivePartObject != NULL) {
ActivePartObject->removeFeature(pcGroove);
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = ActivePartObject->Tip.getValue();
App::DocumentObject* prev = ActivePartObject->getPrevSolidFeature();
@ -350,21 +357,6 @@ bool TaskDlgGrooveParameters::reject()
}
}
// role back the done things
Gui::Command::abortCommand();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()");
// if abort command deleted the object the support is visible again
if (!Gui::Application::Instance->getViewProvider(pcGroove)) {
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
Gui::Application::Instance->getViewProvider(pcSketch)->show();
if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport))
Gui::Application::Instance->getViewProvider(pcSupport)->show();
}
//Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
//Gui::Command::commitCommand();
return true;
}

View File

@ -553,20 +553,7 @@ bool TaskDlgPadParameters::reject()
Sketcher::SketchObject *pcSketch = 0;
if (pcPad->Sketch.getValue()) {
pcSketch = static_cast<Sketcher::SketchObject*>(pcPad->Sketch.getValue());
}
// Body housekeeping
if (ActivePartObject != NULL) {
ActivePartObject->removeFeature(pcPad);
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = ActivePartObject->Tip.getValue();
App::DocumentObject* prev = ActivePartObject->getPrevSolidFeature();
if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
}
}
}
// roll back the done things
Gui::Command::abortCommand();
@ -578,6 +565,18 @@ bool TaskDlgPadParameters::reject()
Gui::Application::Instance->getViewProvider(pcSketch)->show();
}
// Body housekeeping
if (ActivePartObject != NULL) {
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = ActivePartObject->Tip.getValue();
App::DocumentObject* prev = ActivePartObject->getPrevSolidFeature();
if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
}
}
return true;
}

View File

@ -495,15 +495,22 @@ bool TaskDlgPocketParameters::reject()
// get the support and Sketch
PartDesign::Pocket* pcPocket = static_cast<PartDesign::Pocket*>(PocketView->getObject());
Sketcher::SketchObject *pcSketch = 0;
App::DocumentObject *pcSupport = 0;
if (pcPocket->Sketch.getValue()) {
pcSketch = static_cast<Sketcher::SketchObject*>(pcPocket->Sketch.getValue());
pcSupport = pcSketch->Support.getValue();
pcSketch = static_cast<Sketcher::SketchObject*>(pcPocket->Sketch.getValue());
}
// roll back the done things
Gui::Command::abortCommand();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()");
// if abort command deleted the object the sketch is visible again
if (!Gui::Application::Instance->getViewProvider(pcPocket)) {
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
Gui::Application::Instance->getViewProvider(pcSketch)->show();
}
// Body housekeeping
if (ActivePartObject != NULL) {
ActivePartObject->removeFeature(pcPocket);
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = ActivePartObject->Tip.getValue();
App::DocumentObject* prev = ActivePartObject->getPrevSolidFeature();
@ -514,21 +521,6 @@ bool TaskDlgPocketParameters::reject()
}
}
// roll back the done things
Gui::Command::abortCommand();
Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()");
// if abort command deleted the object the support is visible again
if (!Gui::Application::Instance->getViewProvider(pcPocket)) {
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
Gui::Application::Instance->getViewProvider(pcSketch)->show();
if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport))
Gui::Application::Instance->getViewProvider(pcSupport)->show();
}
//Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
//Gui::Command::commitCommand();
return true;
}

View File

@ -332,23 +332,8 @@ bool TaskDlgRevolutionParameters::reject()
// get the support and Sketch
PartDesign::Revolution* pcRevolution = static_cast<PartDesign::Revolution*>(RevolutionView->getObject());
Sketcher::SketchObject *pcSketch = 0;
App::DocumentObject *pcSupport = 0;
if (pcRevolution->Sketch.getValue()) {
pcSketch = static_cast<Sketcher::SketchObject*>(pcRevolution->Sketch.getValue());
pcSupport = pcSketch->Support.getValue();
}
// Body housekeeping
if (ActivePartObject != NULL) {
ActivePartObject->removeFeature(pcRevolution);
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = ActivePartObject->Tip.getValue();
App::DocumentObject* prev = ActivePartObject->getPrevSolidFeature();
if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
}
}
// role back the done things
@ -359,12 +344,19 @@ bool TaskDlgRevolutionParameters::reject()
if (!Gui::Application::Instance->getViewProvider(pcRevolution)) {
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
Gui::Application::Instance->getViewProvider(pcSketch)->show();
if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport))
Gui::Application::Instance->getViewProvider(pcSupport)->show();
}
//Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
//Gui::Command::commitCommand();
// Body housekeeping
if (ActivePartObject != NULL) {
// Make the new Tip and the previous solid feature visible again
App::DocumentObject* tip = ActivePartObject->Tip.getValue();
App::DocumentObject* prev = ActivePartObject->getPrevSolidFeature();
if (tip != NULL) {
Gui::Application::Instance->getViewProvider(tip)->show();
if ((tip != prev) && (prev != NULL))
Gui::Application::Instance->getViewProvider(prev)->show();
}
}
return true;
}