Model.h
Model_Application.h
Model_Document.h
+ Model_Objects.h
Model_Session.h
Model_Data.h
Model_AttributeDouble.h
SET(PROJECT_SOURCES
Model_Application.cpp
Model_Document.cpp
+ Model_Objects.cpp
Model_Session.cpp
Model_Data.cpp
Model_AttributeDouble.cpp
bool isRoot = theDocID == "root"; // the document is root
std::shared_ptr<Model_Document> aNew(
new Model_Document(theDocID, isRoot ? thePartSetKind : thePartKind));
+ aNew->setThis(aNew);
myDocs[theDocID] = aNew;
// load it if it must be loaded by demand
#include "Model_AttributeRefAttr.h"
#include "Model_Application.h"
#include "Model_Data.h"
+#include "Model_Objects.h"
#include <ModelAPI_Feature.h>
using namespace std;
owner()->document());
if (aDoc) {
TDF_Label aRefLab = myRef->Get();
- return aDoc->object(aRefLab);
+ return aDoc->objects()->object(aRefLab);
}
}
// not initialized
#include "Model_AttributeRefList.h"
#include "Model_Application.h"
#include "Model_Data.h"
+#include "Model_Objects.h"
#include <ModelAPI_Feature.h>
#include <TDF_ListIteratorOfLabelList.hxx>
if (aDoc) {
const TDF_LabelList& aList = myRef->List();
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
- ObjectPtr anObj = aDoc->object(aLIter.Value());
+ ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
if (anObj.get() == NULL) {
myRef->Remove(aLIter.Value());
REMOVE_BACK_REF(theObject);
if (aDoc) {
const TDF_LabelList& aList = myRef->List();
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
- ObjectPtr anObj = aDoc->object(aLIter.Value());
+ ObjectPtr anObj = aDoc->objects()->object(aLIter.Value());
aResult.push_back(anObj);
}
}
int anIndex = 0;
for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next(), anIndex++) {
if (anIndex == theIndex)
- return aDoc->object(aLIter.Value());
+ return aDoc->objects()->object(aLIter.Value());
}
}
return ObjectPtr();
#include "Model_Application.h"
#include "Model_Events.h"
#include "Model_Data.h"
+#include "Model_Objects.h"
#include <ModelAPI_Feature.h>
#include <ModelAPI_Session.h>
if (myRef->Label().FindAttribute(TDataStd_AsciiString::GetID(), anEntry)) {
std::shared_ptr<Model_Document> aDR = std::dynamic_pointer_cast<Model_Document>(aRefDoc);
TDF_Label aRefLab;
- TDF_Tool::Label(aDR->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab);
+ TDF_Tool::Label(aDR->objects()->featuresLabel().Data(), anEntry->Get().ToCString(), aRefLab);
if (!aRefLab.IsNull()) {
- return aDR->object(aRefLab);
+ return aDR->objects()->object(aRefLab);
}
}
}
if (aDoc) {
TDF_Label aRefLab = myRef->Get();
if (!aRefLab.IsNull()) { // it may happen with old document, issue #285
- return aDoc->object(aRefLab);
+ return aDoc->objects()->object(aRefLab);
}
}
}
}
friend class Model_Document;
+ friend class Model_Objects;
friend class Model_Update;
friend class Model_AttributeReference;
friend class Model_AttributeRefAttr;
#include <Model_Document.h>
#include <Model_Data.h>
+#include <Model_Objects.h>
#include <Model_Application.h>
#include <Model_Session.h>
#include <Model_Events.h>
-#include <Model_ResultPart.h>
-#include <Model_ResultConstruction.h>
-#include <Model_ResultBody.h>
-#include <Model_ResultGroup.h>
-#include <Model_ResultParameter.h>
+#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_CompositeFeature.h>
static const int UNDO_LIMIT = 1000; // number of possible undo operations (big for sketcher)
static const int TAG_GENERAL = 1; // general properties tag
-static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results)
-static const int TAG_HISTORY = 3; // tag of the history sub-tree (python dump)
// general sub-labels
static const int TAG_CURRENT_FEATURE = 1; ///< where the reference to the current feature label is located (or no attribute if null feature)
-// feature sub-labels
-static const int TAG_FEATURE_ARGUMENTS = 1; ///< where the arguments are located
-static const int TAG_FEATURE_RESULTS = 2; ///< where the results are located
-
-///
-/// 0:1:2 - where features are located
-/// 0:1:2:N:1 - data of the feature N
-/// 0:1:2:N:2:K:1 - data of the K result of the feature N
-
Model_Document::Model_Document(const std::string theID, const std::string theKind)
: myID(theID), myKind(theKind),
myDoc(new TDocStd_Document("BinOcaf")) // binary OCAF format
{
+ myObjs = new Model_Objects(myDoc->Main());
myDoc->SetUndoLimit(UNDO_LIMIT);
myTransactionSave = 0;
myExecuteFeatures = true;
myDoc->CommitCommand();
}
+void Model_Document::setThis(DocumentPtr theDoc)
+{
+ myObjs->setOwner(theDoc);
+}
+
/// Returns the file name of this document by the nameof directory and identifuer of a document
static TCollection_ExtendedString DocFileName(const char* theFileName, const std::string& theID)
{
std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
aSession->setActiveDocument(anApp->getDocument(myID), false);
aSession->setCheckTransactions(false);
- synchronizeFeatures(false, true, true);
+ DocumentPtr aThis = myObjs->owner();
+ delete myObjs;
+ myObjs = new Model_Objects(myDoc->Main()); // synchronisation is inside
+ myObjs->setOwner(aThis);
aSession->setCheckTransactions(true);
aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
aSession->setActiveDocument(anApp->getDocument(myID), true);
// close for thid document needs no transaction in this document
std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(false);
- // delete all features of this document
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- Events_Loop* aLoop = Events_Loop::loop();
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myObjs);
- for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
- FeaturePtr aFeature = aFeaturesIter.Value();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
- aFeature->eraseResults();
- if (theForever) { // issue #294: do not delete content of the document until it can be redone
- aFeature->erase();
- } else {
- aFeature->data()->execState(ModelAPI_StateMustBeUpdated);
- }
- }
- if (theForever) {
- myObjs.Clear();
- }
- aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
- aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-
// close all only if it is really asked, otherwise it can be undoed/redoed
if (theForever) {
+ delete myObjs;
+ myObjs = 0;
if (myDoc->CanClose() == CDM_CCS_OK)
myDoc->Close();
+ } else {
+ setCurrentFeature(FeaturePtr(), false); // disables all features
}
std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(true);
bool isNestedClosed = !myDoc->HasOpenCommand() && !myNestedNum.empty();
static std::shared_ptr<Model_Session> aSession =
std::static_pointer_cast<Model_Session>(Model_Session::get());
- synchronizeBackRefs();
+ myObjs->synchronizeBackRefs();
Events_Loop* aLoop = Events_Loop::loop();
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->abortOperation();
// references may be changed because they are set in attributes on the fly
- synchronizeFeatures(true, true, isRoot());
+ myObjs->synchronizeFeatures(true, true, isRoot());
}
bool Model_Document::isOperation() const
}
// after redo of all sub-documents to avoid updates on not-modified data (issue 370)
if (theSynchronize)
- synchronizeFeatures(true, true, isRoot());
+ myObjs->synchronizeFeatures(true, true, isRoot());
}
void Model_Document::undo()
subDoc(*aSubIter)->redo();
// after redo of all sub-documents to avoid updates on not-modified data (issue 370)
- synchronizeFeatures(true, true, isRoot());
+ myObjs->synchronizeFeatures(true, true, isRoot());
}
std::list<std::string> Model_Document::undoList() const
myTransactions.rbegin()->myId = theId;
}
-/// Append to the array of references a new referenced label
-static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced)
-{
- Handle(TDataStd_ReferenceArray) aRefs;
- if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
- aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0);
- aRefs->SetValue(0, theReferenced);
- } else { // extend array by one more element
- Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
- aRefs->Upper() + 1);
- for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
- aNewArray->SetValue(a, aRefs->Value(a));
- }
- aNewArray->SetValue(aRefs->Upper() + 1, theReferenced);
- aRefs->SetInternalArray(aNewArray);
- }
-}
-
FeaturePtr Model_Document::addFeature(std::string theID)
{
- TDF_Label anEmptyLab;
- FeaturePtr anEmptyFeature;
std::shared_ptr<Model_Session> aSession =
std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
FeaturePtr aFeature = aSession->createFeature(theID, this);
aDocToAdd = this;
}
if (aFeature) {
- TDF_Label aFeatureLab;
- if (!aFeature->isAction()) { // do not add action to the data model
- TDF_Label aFeaturesLab = aDocToAdd->featuresLabel();
- aFeatureLab = aFeaturesLab.NewChild();
- aDocToAdd->initData(aFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
- // keep the feature ID to restore document later correctly
- TDataStd_Comment::Set(aFeatureLab, aFeature->getKind().c_str());
- aDocToAdd->myObjs.Bind(aFeatureLab, aFeature);
- // store feature in the history of features array
- if (aFeature->isInHistory()) {
- AddToRefArray(aFeaturesLab, aFeatureLab);
- }
- }
+ aDocToAdd->myObjs->addFeature(aFeature, currentFeature(false));
if (!aFeature->isAction()) { // do not add action to the data model
- // event: feature is added
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
- aFeature->setDisabled(false); // by default created feature is enabled
setCurrentFeature(aFeature, false); // after all this feature stays in the document, so make it current
} else { // feature must be executed
// no creation event => updater not working, problem with remove part
return aFeature;
}
-/// Appenad to the array of references a new referenced label.
-/// If theIndex is not -1, removes element at this index, not theReferenced.
-/// \returns the index of removed element
-static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced,
- const int theIndex = -1)
-{
- int aResult = -1; // no returned
- Handle(TDataStd_ReferenceArray) aRefs;
- if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
- if (aRefs->Length() == 1) { // just erase an array
- if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
- theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
- }
- aResult = 0;
- } else { // reduce the array
- Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
- aRefs->Upper() - 1);
- int aCount = aRefs->Lower();
- for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) {
- if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) {
- aCount--;
- aResult = a;
- } else {
- aNewArray->SetValue(aCount, aRefs->Value(a));
- }
- }
- aRefs->SetInternalArray(aNewArray);
- }
- }
- return aResult;
-}
void Model_Document::refsToFeature(FeaturePtr theFeature,
- std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs,
- const bool isSendError)
+ std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs, const bool isSendError)
{
- // check the feature: it must have no depended objects on it
- // the dependencies can be in the feature results
- std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
- for(; aResIter != theFeature->results().cend(); aResIter++) {
- ResultPtr aResult = (*aResIter);
- std::shared_ptr<Model_Data> aData =
- std::dynamic_pointer_cast<Model_Data>(aResult->data());
- if (aData.get() != NULL) {
- const std::set<AttributePtr>& aRefs = aData->refsToMe();
- std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
- for(; aRefIt != aRefLast; aRefIt++) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
- if (aFeature.get() != NULL)
- theRefs.insert(aFeature);
- }
- }
- }
- // the dependencies can be in the feature itself
- std::shared_ptr<Model_Data> aData =
- std::dynamic_pointer_cast<Model_Data>(theFeature->data());
- if (aData && !aData->refsToMe().empty()) {
- const std::set<AttributePtr>& aRefs = aData->refsToMe();
- std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
- for(; aRefIt != aRefLast; aRefIt++) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
- if (aFeature.get() != NULL)
- theRefs.insert(aFeature);
- }
- }
-
- if (!theRefs.empty() && isSendError) {
- Events_Error::send(
- "Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
- }
+ myObjs->refsToFeature(theFeature, theRefs, isSendError);
}
-void Model_Document::removeFeature(FeaturePtr theFeature/*, const bool theCheck*/)
+void Model_Document::removeFeature(FeaturePtr theFeature)
{
- std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
- if (aData) {
- TDF_Label aFeatureLabel = aData->label().Father();
- if (myObjs.IsBound(aFeatureLabel))
- myObjs.UnBind(aFeatureLabel);
- else
- return; // not found feature => do not remove
-
- // checking that the sub-element of composite feature is removed: if yes, inform the owner
- std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
- refsToFeature(theFeature, aRefs, false);
- std::set<std::shared_ptr<ModelAPI_Feature> >::iterator aRefIter = aRefs.begin();
- for(; aRefIter != aRefs.end(); aRefIter++) {
- std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
- if (aComposite.get()) {
- aComposite->removeFeature(theFeature);
- }
- }
- // if this feature is current, make the current the previous feature
- if (theFeature == currentFeature(false)) {
- int aCurrentIndex = index(theFeature);
- if (aCurrentIndex != -1) {
- setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(
- object(ModelAPI_Feature::group(), aCurrentIndex - 1)), false);
- }
- }
-
- // erase fields
- theFeature->erase();
- static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
- // erase all attributes under the label of feature
- aFeatureLabel.ForgetAllAttributes();
- // remove it from the references array
- if (theFeature->isInHistory()) {
- RemoveFromRefArray(featuresLabel(), aFeatureLabel);
+ // if this feature is current, make the current the previous feature
+ if (theFeature == currentFeature(false)) {
+ int aCurrentIndex = index(theFeature);
+ if (aCurrentIndex != -1) {
+ setCurrentFeature(std::dynamic_pointer_cast<ModelAPI_Feature>(
+ object(ModelAPI_Feature::group(), aCurrentIndex - 1)), false);
}
- // event: feature is deleted
- ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
- // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
- Events_Loop::loop()->flush(EVENT_DISP);
}
+ myObjs->removeFeature(theFeature);
}
-void Model_Document::addToHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+void Model_Document::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
{
- TDF_Label aFeaturesLab = featuresLabel();
- std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theObject->data());
- if (!aData) {
- return; // not found feature => do not remove
- }
- TDF_Label aFeatureLabel = aData->label().Father();
- // store feature in the history of features array
- if (theObject->isInHistory()) {
- AddToRefArray(aFeaturesLab, aFeatureLabel);
- } else {
- RemoveFromRefArray(aFeaturesLab, aFeatureLabel);
- }
-}
-
-FeaturePtr Model_Document::feature(TDF_Label& theLabel) const
-{
- if (myObjs.IsBound(theLabel))
- return myObjs.Find(theLabel);
- return FeaturePtr(); // not found
+ myObjs->updateHistory(theObject);
}
-ObjectPtr Model_Document::object(TDF_Label theLabel)
+void Model_Document::updateHistory(const std::string theGroup)
{
- // try feature by label
- FeaturePtr aFeature = feature(theLabel);
- if (aFeature)
- return feature(theLabel);
- TDF_Label aFeatureLabel = theLabel.Father().Father(); // let's suppose it is result
- aFeature = feature(aFeatureLabel);
- if (aFeature) {
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
- for (; aRIter != aResults.cend(); aRIter++) {
- std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
- (*aRIter)->data());
- if (aResData->label().Father().IsEqual(theLabel))
- return *aRIter;
- }
- }
- return FeaturePtr(); // not found
+ myObjs->updateHistory(theGroup);
}
std::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string theDocID)
const std::set<std::string> Model_Document::subDocuments(const bool theActivatedOnly) const
{
std::set<std::string> aResult;
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (aFeature.get()) { // if document is closed the feature may be not in myObjs map
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() != ModelAPI_ResultPart::group()) continue;
- if ((*aRIter)->isInHistory()) {
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
- if (aPart && (!theActivatedOnly || aPart->isActivated()))
- aResult.insert(aPart->data()->name());
- }
- }
- }
+ int aNum = myObjs->size(ModelAPI_ResultPart::group());
+ for(int a = 0; a < aNum; a++) {
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(
+ myObjs->object(ModelAPI_ResultPart::group(), a));
+ if (aPart && (!theActivatedOnly || aPart->isActivated()))
+ aResult.insert(aPart->data()->name());
}
return aResult;
}
Model_Application::getApplication()->getDocument(theDocID));
}
-ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex,
- const bool theHidden)
+ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex)
{
- if (theGroupID == ModelAPI_Feature::group()) {
- if (theHidden) {
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- if (theIndex == anIndex) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- return feature(aFLabel);
- }
- anIndex++;
- }
- } else {
- Handle(TDataStd_ReferenceArray) aRefs;
- if (!featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
- return ObjectPtr();
- if (aRefs->Lower() > theIndex || aRefs->Upper() < theIndex)
- return ObjectPtr();
- TDF_Label aFeatureLabel = aRefs->Value(theIndex);
- return feature(aFeatureLabel);
- }
- } else {
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() != theGroupID) continue;
- bool isIn = theHidden && (*aRIter)->isInHistory();
- if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result
- isIn = !(*aRIter)->isConcealed();
- }
- if (isIn) {
- if (anIndex == theIndex)
- return *aRIter;
- anIndex++;
- }
- }
- }
- }
- // not found
- return ObjectPtr();
+ return myObjs->object(theGroupID, theIndex);
}
std::shared_ptr<ModelAPI_Object> Model_Document::objectByName(
const std::string& theGroupID, const std::string& theName)
{
- if (theGroupID == ModelAPI_Feature::group()) {
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (aFeature && aFeature->name() == theName)
- return aFeature;
- }
- } else {
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() == theGroupID && (*aRIter)->data()->name() == theName)
- return *aRIter;
- }
- }
- }
- // not found
- return ObjectPtr();
+ return myObjs->objectByName(theGroupID, theName);
}
const int Model_Document::index(std::shared_ptr<ModelAPI_Object> theObject)
{
- const std::string aGroupName = theObject->groupName();
- if (aGroupName == ModelAPI_Feature::group()) {
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (aFeature == theObject)
- return anIndex;
- if (aFeature->isInHistory())
- anIndex++;
- }
- } else {
- // comment must be in any feature: it is kind
- int anIndex = 0;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if (*aRIter == theObject)
- return anIndex;
- if ((*aRIter)->groupName() == aGroupName) {
- bool isIn = (*aRIter)->isInHistory() && !(*aRIter)->isConcealed();
- if (isIn) {
- anIndex++;
- }
- }
- }
- }
- }
- // not found
- return -1;
+ return myObjs->index(theObject);
}
-int Model_Document::size(const std::string& theGroupID, const bool theHidden)
+int Model_Document::size(const std::string& theGroupID)
{
- int aResult = 0;
- if (theGroupID == ModelAPI_Feature::group()) {
- if (theHidden) {
- return myObjs.Size();
- } else {
- Handle(TDataStd_ReferenceArray) aRefs;
- if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs))
- return aRefs->Length();
- }
- } else {
- // comment must be in any feature: it is kind
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature = feature(aFLabel);
- if (!aFeature) // may be on close
- continue;
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if ((*aRIter)->groupName() != theGroupID) continue;
- bool isIn = theHidden;
- if (!isIn && (*aRIter)->isInHistory()) { // check that there is nobody references this result
- isIn = !(*aRIter)->isConcealed();
- }
- if (isIn)
- aResult++;
- }
- }
- }
- // group is not found
- return aResult;
+ return myObjs->size(theGroupID);
}
std::shared_ptr<ModelAPI_Feature> Model_Document::currentFeature(const bool theVisible)
Handle(TDF_Reference) aRef;
if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
TDF_Label aLab = aRef->Get();
- FeaturePtr aResult = feature(aLab);
+ FeaturePtr aResult = myObjs->feature(aLab);
if (theVisible) { // get nearest visible (in history) going up
- int aTag = aLab.Tag();
- while(aTag > 1 && (!aResult.get() || !aResult->isInHistory())) {
- aTag--;
- aLab = aLab.Father().FindChild(aTag);
- aResult = feature(aLab);
+ while(aResult.get() && !aResult->isInHistory()) {
+ aResult = myObjs->nextFeature(aResult, true);
}
- if (aTag <= 1)
- aResult.reset();
}
return aResult;
}
{
TDF_Label aRefLab = generalLabel().FindChild(TAG_CURRENT_FEATURE);
if (theCurrent.get()) {
- std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
- if (aData.get()) {
- TDF_Label aFeatureLabel = aData->label().Father();
- if (theVisible) { // make features below which are not in history also enabled: sketch subs
- int aTag = aFeatureLabel.Tag();
- FeaturePtr aNextFeature;
- TDF_Label aNextLabel;
- for(aTag++; true; aTag++) {
- TDF_Label aLabel = aFeatureLabel.Father().FindChild(aTag, 0);
- if (aLabel.IsNull())
- break;
- FeaturePtr aFeature = feature(aLabel);
- if (aFeature.get()) {
- if (aFeature->isInHistory())
- break;
- aNextFeature = aFeature;
- aNextLabel = aLabel;
- }
+ if (theVisible) { // make features below which are not in history also enabled: sketch subs
+ FeaturePtr aNext = myObjs->nextFeature(theCurrent);
+ for (; aNext.get(); aNext = myObjs->nextFeature(theCurrent)) {
+ if (aNext->isInHistory()) {
+ break; // next in history is not needed
+ } else { // next not in history is good for making current
+ theCurrent = aNext;
}
- if (aNextFeature.get()) {
- theCurrent = aNextFeature;
- aFeatureLabel = aNextLabel;
- }
- }
- Handle(TDF_Reference) aRef;
- if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
- aRef->Set(aFeatureLabel);
- } else {
- aRef = TDF_Reference::Set(aRefLab, aFeatureLabel);
}
}
+ std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
+ if (!aData.get()) return; // unknown case
+ TDF_Label aFeatureLabel = aData->label().Father();
+
+ Handle(TDF_Reference) aRef;
+ if (aRefLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
+ aRef->Set(aFeatureLabel);
+ } else {
+ aRef = TDF_Reference::Set(aRefLab, aFeatureLabel);
+ }
} else { // remove reference for the null feature
aRefLab.ForgetAttribute(TDF_Reference::GetID());
}
// make all features after this feature disabled in reversed order (to remove results without deps)
bool aPassed = false; // flag that the current object is already passed in cycle
- int aSize = size(ModelAPI_Feature::group(), true);
- for(int a = aSize - 1; a >= 0; a--) {
- FeaturePtr aFeature =
- std::dynamic_pointer_cast<ModelAPI_Feature>(object(ModelAPI_Feature::group(), a, true));
-
+ FeaturePtr anIter = myObjs->lastFeature();
+ for(; anIter.get(); anIter = myObjs->nextFeature(anIter, true)) {
// check this before passed become enabled: the current feature is enabled!
- if (aFeature == theCurrent) aPassed = true;
+ if (anIter == theCurrent) aPassed = true;
- if (aFeature->setDisabled(!aPassed)) {
+ if (anIter->setDisabled(!aPassed)) {
// state of feature is changed => so feature become updated
static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
+ ModelAPI_EventCreator::get()->sendUpdated(anIter, anUpdateEvent);
}
}
}
-TDF_Label Model_Document::featuresLabel() const
-{
- return myDoc->Main().FindChild(TAG_OBJECTS);
-}
-
TDF_Label Model_Document::generalLabel() const
{
return myDoc->Main().FindChild(TAG_GENERAL);
}
-void Model_Document::setUniqueName(FeaturePtr theFeature)
-{
- if (!theFeature->data()->name().empty())
- return; // not needed, name is already defined
- std::string aName; // result
- // first count all objects of such kind to start with index = count + 1
- int aNumObjects = 0;
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
- for (; aFIter.More(); aFIter.Next()) {
- if (aFIter.Value()->getKind() == theFeature->getKind())
- aNumObjects++;
- }
- // generate candidate name
- std::stringstream aNameStream;
- aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
- aName = aNameStream.str();
- // check this is unique, if not, increase index by 1
- for (aFIter.Initialize(myObjs); aFIter.More();) {
- FeaturePtr aFeature = aFIter.Value();
- bool isSameName = aFeature->data()->name() == aName;
- if (!isSameName) { // check also results to avoid same results names (actual for Parts)
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- isSameName = (*aRIter)->data()->name() == aName;
- }
- }
- if (isSameName) {
- aNumObjects++;
- std::stringstream aNameStream;
- aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
- aName = aNameStream.str();
- // reinitialize iterator to make sure a new name is unique
- aFIter.Initialize(myObjs);
- } else
- aFIter.Next();
- }
- theFeature->data()->setName(aName);
-}
-
-void Model_Document::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
-{
- std::shared_ptr<ModelAPI_Document> aThis = Model_Application::getApplication()->getDocument(
- myID);
- std::shared_ptr<Model_Data> aData(new Model_Data);
- aData->setLabel(theLab.FindChild(theTag));
- aData->setObject(theObj);
- theObj->setDoc(aThis);
- theObj->setData(aData);
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
- if (aFeature) {
- setUniqueName(aFeature); // must be before "initAttributes" because duplicate part uses name
- }
- theObj->initAttributes();
-}
-
-void Model_Document::synchronizeFeatures(
- const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- // after all updates, sends a message that groups of features were created or updated
- Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- aLoop->activateFlushes(false);
-
- // update all objects by checking are they on labels or not
- std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
- TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter.More(); aLabIter.Next()) {
- TDF_Label aFeatureLabel = aLabIter.Value()->Label();
- FeaturePtr aFeature;
- if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
- // create a feature
- aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
- TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
- .ToCString(), this);
- if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure
- Events_Error::send("Invalid type of object in the document");
- aLabIter.Value()->Label().ForgetAllAttributes();
- continue;
- }
- // this must be before "setData" to redo the sketch line correctly
- myObjs.Bind(aFeatureLabel, aFeature);
- aNewFeatures.insert(aFeature);
- initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
-
- // event: model is updated
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
- } else { // nothing is changed, both iterators are incremented
- aFeature = myObjs.Find(aFeatureLabel);
- aKeptFeatures.insert(aFeature);
- if (theMarkUpdated) {
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
- }
- }
- }
- // update results of the features (after features created because they may be connected, like sketch and sub elements)
- std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
- TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
- for (; aLabIter2.More(); aLabIter2.Next()) {
- TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
- if (myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted
- FeaturePtr aFeature = myObjs.Find(aFeatureLabel);
- if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
- aComposites.push_back(aFeature);
- updateResults(aFeature);
- }
- }
- std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
- for(; aComposite != aComposites.end(); aComposite++) {
- updateResults(*aComposite);
- }
-
- // check all features are checked: if not => it was removed
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
- while (aFIter.More()) {
- if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
- && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
- FeaturePtr aFeature = aFIter.Value();
- // event: model is updated
- //if (aFeature->isInHistory()) {
- ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
- //}
- // results of this feature must be redisplayed (hided)
- // redisplay also removed feature (used for sketch and AISObject)
- ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
- aFeature->erase();
- // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
- myObjs.UnBind(aFIter.Key());
- // reinitialize iterator because unbind may corrupt the previous order in the map
- aFIter.Initialize(myObjs);
- } else
- aFIter.Next();
- }
-
- if (theUpdateReferences) {
- synchronizeBackRefs();
- }
-
- myExecuteFeatures = false;
- aLoop->activateFlushes(true);
-
- if (theFlush) {
- aLoop->flush(aCreateEvent);
- aLoop->flush(aDeleteEvent);
- aLoop->flush(anUpdateEvent);
- aLoop->flush(aRedispEvent);
- aLoop->flush(aToHideEvent);
- }
- myExecuteFeatures = true;
-}
-
-void Model_Document::synchronizeBackRefs()
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- // keeps the concealed flags of result to catch the change and create created/deleted events
- std::list<std::pair<ResultPtr, bool> > aConcealed;
- // first cycle: erase all data about back-references
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myObjs);
- for(; aFeatures.More(); aFeatures.Next()) {
- FeaturePtr aFeature = aFeatures.Value();
- std::shared_ptr<Model_Data> aFData =
- std::dynamic_pointer_cast<Model_Data>(aFeature->data());
- if (aFData) {
- aFData->eraseBackReferences();
- }
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- std::shared_ptr<Model_Data> aResData =
- std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
- if (aResData) {
- aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
- aResData->eraseBackReferences();
- }
- }
- }
-
- // second cycle: set new back-references: only features may have reference, iterate only them
- ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
- for(aFeatures.Initialize(myObjs); aFeatures.More(); aFeatures.Next()) {
- FeaturePtr aFeature = aFeatures.Value();
- std::shared_ptr<Model_Data> aFData =
- std::dynamic_pointer_cast<Model_Data>(aFeature->data());
- if (aFData) {
- std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
- aFData->referencesToObjects(aRefs);
- std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator
- aRefsIter = aRefs.begin();
- for(; aRefsIter != aRefs.end(); aRefsIter++) {
- std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
- for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
- if (*aRefTo) {
- std::shared_ptr<Model_Data> aRefData =
- std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
- aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
- }
- }
- }
- }
- }
- std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
- for(; aCIter != aConcealed.end(); aCIter++) {
- if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
- if (aCIter->second) { // was concealed become not => creation event
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent);
- } else { // was not concealed become concealed => delete event
- ModelAPI_EventCreator::get()->sendDeleted(aThis, aCIter->first->groupName());
- // redisplay for the viewer (it must be disappeared also)
- static Events_ID EVENT_DISP =
- Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP);
- }
- }
- }
-}
-
-TDF_Label Model_Document::resultLabel(
- const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex)
-{
- const std::shared_ptr<Model_Data>& aData =
- std::dynamic_pointer_cast<Model_Data>(theFeatureData);
- return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
-}
-
-void Model_Document::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
- std::shared_ptr<ModelAPI_Result> theResult,
- const int theResultIndex)
-{
- std::shared_ptr<ModelAPI_Document> aThis =
- Model_Application::getApplication()->getDocument(myID);
- theResult->setDoc(aThis);
- initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
- if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name
- std::stringstream aNewName;
- aNewName<<theFeatureData->name();
- if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
- aNewName<<"_"<<theResultIndex + 1;
- theResult->data()->setName(aNewName.str());
- }
-}
-
std::shared_ptr<ModelAPI_ResultConstruction> Model_Document::createConstruction(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultConstruction> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultConstruction>(new Model_ResultConstruction);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createConstruction(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultBody> Model_Document::createBody(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultBody> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createBody(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultPart> Model_Document::createPart(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultPart> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultPart>(new Model_ResultPart);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createPart(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultGroup> Model_Document::createGroup(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultGroup> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultGroup>(new Model_ResultGroup(theFeatureData));
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createGroup(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_ResultParameter> Model_Document::createParameter(
const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
{
- TDF_Label aLab = resultLabel(theFeatureData, theIndex);
- TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
- ObjectPtr anOldObject = object(aLab);
- std::shared_ptr<ModelAPI_ResultParameter> aResult;
- if (anOldObject) {
- aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
- }
- if (!aResult) {
- aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
- storeResult(theFeatureData, aResult, theIndex);
- }
- return aResult;
+ return myObjs->createParameter(theFeatureData, theIndex);
}
std::shared_ptr<ModelAPI_Feature> Model_Document::feature(
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
if (aData) {
TDF_Label aFeatureLab = aData->label().Father().Father().Father();
- return feature(aFeatureLab);
+ return myObjs->feature(aFeatureLab);
}
return FeaturePtr();
}
-void Model_Document::updateResults(FeaturePtr theFeature)
-{
- // for not persistent is will be done by parametric updater automatically
- //if (!theFeature->isPersistentResult()) return;
- // check the existing results and remove them if there is nothing on the label
- std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
- while(aResIter != theFeature->results().cend()) {
- ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
- if (aBody) {
- if (!aBody->data()->isValid()) {
- // found a disappeared result => remove it
- theFeature->removeResult(aBody);
- // start iterate from beginning because iterator is corrupted by removing
- aResIter = theFeature->results().cbegin();
- continue;
- }
- }
- aResIter++;
- }
- // it may be on undo
- if (!theFeature->data() || !theFeature->data()->isValid())
- return;
- // check that results are presented on all labels
- int aResSize = theFeature->results().size();
- TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
- for(; aLabIter.More(); aLabIter.Next()) {
- // here must be GUID of the feature
- int aResIndex = aLabIter.Value().Tag() - 1;
- ResultPtr aNewBody;
- if (aResSize <= aResIndex) {
- TDF_Label anArgLab = aLabIter.Value();
- Handle(TDataStd_Comment) aGroup;
- if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
- if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
- aNewBody = createBody(theFeature->data(), aResIndex);
- } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
- aNewBody = createPart(theFeature->data(), aResIndex);
- } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
- theFeature->execute(); // construction shapes are needed for sketch solver
- break;
- } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
- aNewBody = createGroup(theFeature->data(), aResIndex);
- } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
- theFeature->attributeChanged("expression"); // just produce a value
- break;
- } else {
- Events_Error::send(std::string("Unknown type of result is found in the document:") +
- TCollection_AsciiString(aGroup->Get()).ToCString());
- }
- }
- if (aNewBody) {
- theFeature->setResult(aNewBody, aResIndex);
- }
- }
- }
-}
-
Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
{
return TDF_LabelMapHasher::HashCode(theLab, theUpper);
ResultPtr Model_Document::findByName(const std::string theName)
{
- NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myObjs);
- for(; anObjIter.More(); anObjIter.Next()) {
- FeaturePtr& aFeature = anObjIter.ChangeValue();
- if (!aFeature) // may be on close
- continue;
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- if (aRIter->get() && (*aRIter)->data() && (*aRIter)->data()->isValid() &&
- (*aRIter)->data()->name() == theName) {
- return *aRIter;
- }
- }
- }
- // not found
- return ResultPtr();
+ return myObjs->findByName(theName);
}
#include <ModelAPI_ResultParameter.h>
#include <TDocStd_Document.hxx>
-#include <NCollection_DataMap.hxx>
-#include <TDF_Label.hxx>
#include <map>
#include <set>
class Handle_Model_Document;
-
-// for TDF_Label map usage
-static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper);
-static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2);
+class Model_Objects;
/**\class Model_Document
* \ingroup DataModel
//! \param theFeature a removed feature
MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature);
- //! Returns the existing feature by the label
- //! \param theLabel base label of the feature
- MODEL_EXPORT virtual FeaturePtr feature(TDF_Label& theLabel) const;
-
- //! Returns the existing object: result or feature
- //! \param theLabel base label of the object
- MODEL_EXPORT virtual ObjectPtr object(TDF_Label theLabel);
-
//! Returns the first found object in the group by the object name
//! \param theGroupID group that contains an object
//! \param theName name of the object to search
//! Returns the feature in the group by the index (started from zero)
//! \param theGroupID group that contains a feature
//! \param theIndex zero-based index of feature in the group
- //! \param theHidden if it is true, it counts also the features that are not in tree
- MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex,
- const bool theHidden = false);
+ MODEL_EXPORT virtual ObjectPtr object(const std::string& theGroupID, const int theIndex);
//! Returns the number of features in the group
- //! If theHidden is true, it counts also the features that are not in tree
- MODEL_EXPORT virtual int size(const std::string& theGroupID, const bool theHidden = false);
+ MODEL_EXPORT virtual int size(const std::string& theGroupID);
//! Returns the feature that is currently edited in this document, normally
//! this is the latest created feature
///! Returns true if parametric updater need to execute feature on recomputartion
///! On abort, undo or redo it is not necessary: results in document are updated automatically
- bool executeFeatures() {return myExecuteFeatures;}
+ bool& executeFeatures() {return myExecuteFeatures;}
//! Registers the name of the shape for the topological naming needs
void addNamingName(const TDF_Label theLabel, std::string theName);
ResultPtr findByName(const std::string theName);
protected:
-
- //! Returns (creates if needed) the features label
- TDF_Label featuresLabel() const;
//! Returns (creates if needed) the general label
TDF_Label generalLabel() const;
- //! Initializes feature with a unique name in this group (unique name is generated as
- //! feature type + "_" + index
- void setUniqueName(FeaturePtr theFeature);
-
- //! Synchronizes myFeatures list with the updated document
- //! \param theMarkUpdated causes the "update" event for all features
- //! \param theUpdateReferences causes the update of back-references
- //! \param theFlush makes flush all events in the end of all modifications of this method
- void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
- const bool theFlush);
- //! Synchronizes the BackReferences list in Data of Features and Results
- void synchronizeBackRefs();
-
//! Creates new document with binary file format
Model_Document(const std::string theID, const std::string theKind);
//! \returns true if resulting transaction is not empty and can be undoed
void compactNested();
- //! Initializes the data fields of the feature
- void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag);
-
- //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree)
- MODEL_EXPORT virtual void storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
- std::shared_ptr<ModelAPI_Result> theResult,
- const int theResultIndex = 0);
-
- //! returns the label of result by index; creates this label if it was not created before
- TDF_Label resultLabel(const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex);
-
- //! Updates the results list of the feature basing on the current data tree
- void updateResults(FeaturePtr theFeature);
-
//! Returns all sub documents
const std::set<std::string> subDocuments(const bool theActivatedOnly) const;
std::list<std::string> redoList() const;
/// Internally makes document know that feature was removed or added in history after creation
- MODEL_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+ virtual void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+ /// Internally makes document know that feature was removed or added in history after creation
+ virtual void updateHistory(const std::string theGroup);
/// Returns true if the document is root module document
bool isRoot() const;
+ /// Sets shared pointer to this
+ void setThis(DocumentPtr theDoc);
+
+ /// Returns the objects manager
+ Model_Objects* objects() {return myObjs;}
+
friend class Model_Application;
friend class Model_Session;
friend class Model_Update;
friend class Model_AttributeReference;
+ friend class Model_AttributeRefAttr;
+ friend class Model_AttributeRefList;
friend class DFBrowser;
private:
std::string myKind; ///< kind of the document in the application
Handle_TDocStd_Document myDoc; ///< OCAF document
+ Model_Objects *myObjs; ///< data manager of this document
+
/// counter value of transaction on the last "save" call, used for "IsModified" method
int myTransactionSave;
/// number of nested transactions performed (list becasue may be nested inside of nested)
std::list<Transaction> myTransactions;
/// list of info about transactions undone (first is oldest undone)
std::list<Transaction> myRedos;
- /// All features managed by this document (not only in history of OB)
- /// For optimization mapped by labels
- NCollection_DataMap<TDF_Label, FeaturePtr> myObjs;
+
/// Optimization for finding the shape-label by topological naming names
std::map<std::string, TDF_Label> myNamingNames;
/// If it is true, features are not executed on update (on abort, undo, redo)
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: Model_Objects.cxx
+// Created: 15 May 2015
+// Author: Mikhail PONIKAROV
+
+#include <Model_Objects.h>
+#include <Model_Data.h>
+#include <Model_Document.h>
+#include <Model_Events.h>
+#include <Model_Session.h>
+#include <Model_ResultPart.h>
+#include <Model_ResultConstruction.h>
+#include <Model_ResultBody.h>
+#include <Model_ResultGroup.h>
+#include <Model_ResultParameter.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_CompositeFeature.h>
+
+#include <Events_Loop.h>
+#include <Events_Error.h>
+
+#include <TDataStd_Integer.hxx>
+#include <TDataStd_Comment.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDataStd_ReferenceArray.hxx>
+#include <TDataStd_HLabelArray1.hxx>
+#include <TDataStd_Name.hxx>
+#include <TDF_Reference.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDF_LabelMapHasher.hxx>
+
+static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results)
+
+// feature sub-labels
+static const int TAG_FEATURE_ARGUMENTS = 1; ///< where the arguments are located
+static const int TAG_FEATURE_RESULTS = 2; ///< where the results are located
+
+///
+/// 0:1:2 - where features are located
+/// 0:1:2:N:1 - data of the feature N
+/// 0:1:2:N:2:K:1 - data of the K result of the feature N
+
+Model_Objects::Model_Objects(TDF_Label theMainLab) : myMain(theMainLab)
+{
+ // update all fields and recreate features and result objects if needed
+ synchronizeFeatures(false, true, true);
+}
+
+Model_Objects::~Model_Objects()
+{
+ // delete all features of this document
+ Events_Loop* aLoop = Events_Loop::loop();
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeaturesIter(myFeatures);
+ for(; aFeaturesIter.More(); aFeaturesIter.Next()) {
+ FeaturePtr aFeature = aFeaturesIter.Value();
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group());
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
+ aFeature->eraseResults();
+ aFeature->erase();
+ }
+ myFeatures.Clear();
+ aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
+ aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+
+}
+
+/// Appends to the array of references a new referenced label
+static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced, TDF_Label& thePrevLab)
+{
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (!theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ aRefs = TDataStd_ReferenceArray::Set(theArrayLab, 0, 0);
+ aRefs->SetValue(0, theReferenced);
+ } else { // extend array by one more element
+ Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
+ aRefs->Upper() + 1);
+ int aPassedPrev = 0; // prev feature is found and passed
+ if (thePrevLab.IsNull()) { // null means that inserted feature must be the first
+ aNewArray->SetValue(aRefs->Lower(), theReferenced);
+ aPassedPrev = 1;
+ }
+ for (int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+ aNewArray->SetValue(a + aPassedPrev, aRefs->Value(a));
+ if (!aPassedPrev && aRefs->Value(a).IsEqual(thePrevLab)) {
+ aPassedPrev = 1;
+ aNewArray->SetValue(a + 1, theReferenced);
+ }
+ }
+ if (!aPassedPrev) // not found: unknown situation
+ aNewArray->SetValue(aRefs->Upper() + 1, theReferenced);
+ aRefs->SetInternalArray(aNewArray);
+ }
+}
+
+void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis)
+{
+ if (!theFeature->isAction()) { // do not add action to the data model
+ TDF_Label aFeaturesLab = featuresLabel();
+ TDF_Label aFeatureLab = aFeaturesLab.NewChild();
+ initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS);
+ // keep the feature ID to restore document later correctly
+ TDataStd_Comment::Set(aFeatureLab, theFeature->getKind().c_str());
+ myFeatures.Bind(aFeatureLab, theFeature);
+ // store feature in the features array
+ TDF_Label aPrevFeateureLab;
+ if (theAfterThis.get()) { // searching for the previous feature label
+ std::shared_ptr<Model_Data> aPrevData =
+ std::dynamic_pointer_cast<Model_Data>(theAfterThis->data());
+ if (aPrevData.get()) {
+ aPrevFeateureLab = aPrevData->label().Father();
+ }
+ }
+ AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab);
+ // event: feature is added
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ ModelAPI_EventCreator::get()->sendUpdated(theFeature, anEvent);
+ theFeature->setDisabled(false); // by default created feature is enabled
+ updateHistory(ModelAPI_Feature::group());
+ }
+}
+
+/// Appends to the array of references a new referenced label.
+/// If theIndex is not -1, removes element at this index, not theReferenced.
+/// \returns the index of removed element
+static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced,
+ const int theIndex = -1)
+{
+ int aResult = -1; // no returned
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (theArrayLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ if (aRefs->Length() == 1) { // just erase an array
+ if ((theIndex == -1 && aRefs->Value(0) == theReferenced) || theIndex == 0) {
+ theArrayLab.ForgetAttribute(TDataStd_ReferenceArray::GetID());
+ }
+ aResult = 0;
+ } else { // reduce the array
+ Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
+ aRefs->Upper() - 1);
+ int aCount = aRefs->Lower();
+ for (int a = aCount; a <= aRefs->Upper(); a++, aCount++) {
+ if ((theIndex == -1 && aRefs->Value(a) == theReferenced) || theIndex == a) {
+ aCount--;
+ aResult = a;
+ } else {
+ aNewArray->SetValue(aCount, aRefs->Value(a));
+ }
+ }
+ aRefs->SetInternalArray(aNewArray);
+ }
+ }
+ return aResult;
+}
+
+void Model_Objects::refsToFeature(FeaturePtr theFeature,
+ std::set<std::shared_ptr<ModelAPI_Feature> >& theRefs, const bool isSendError)
+{
+ // check the feature: it must have no depended objects on it
+ // the dependencies can be in the feature results
+ std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+ for(; aResIter != theFeature->results().cend(); aResIter++) {
+ ResultPtr aResult = (*aResIter);
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(aResult->data());
+ if (aData.get() != NULL) {
+ const std::set<AttributePtr>& aRefs = aData->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
+ for(; aRefIt != aRefLast; aRefIt++) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+ if (aFeature.get() != NULL)
+ theRefs.insert(aFeature);
+ }
+ }
+ }
+ // the dependencies can be in the feature itself
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(theFeature->data());
+ if (aData && !aData->refsToMe().empty()) {
+ const std::set<AttributePtr>& aRefs = aData->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end();
+ for(; aRefIt != aRefLast; aRefIt++) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+ if (aFeature.get() != NULL)
+ theRefs.insert(aFeature);
+ }
+ }
+
+ if (!theRefs.empty() && isSendError) {
+ Events_Error::send(
+ "Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+ }
+}
+
+void Model_Objects::removeFeature(FeaturePtr theFeature)
+{
+ std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
+ if (aData) {
+ TDF_Label aFeatureLabel = aData->label().Father();
+ if (myFeatures.IsBound(aFeatureLabel))
+ myFeatures.UnBind(aFeatureLabel);
+ else
+ return; // not found feature => do not remove
+
+ clearHistory(theFeature);
+ // checking that the sub-element of composite feature is removed: if yes, inform the owner
+ std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
+ refsToFeature(theFeature, aRefs, false);
+ std::set<std::shared_ptr<ModelAPI_Feature> >::iterator aRefIter = aRefs.begin();
+ for(; aRefIter != aRefs.end(); aRefIter++) {
+ std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
+ if (aComposite.get()) {
+ aComposite->removeFeature(theFeature);
+ }
+ }
+ // erase fields
+ theFeature->erase();
+ static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
+ // erase all attributes under the label of feature
+ aFeatureLabel.ForgetAllAttributes();
+ // remove it from the references array
+ if (theFeature->isInHistory()) {
+ RemoveFromRefArray(featuresLabel(), aFeatureLabel);
+ }
+ // event: feature is deleted
+ ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
+ // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
+ Events_Loop::loop()->flush(EVENT_DISP);
+ updateHistory(ModelAPI_Feature::group());
+ }
+}
+
+void Model_Objects::clearHistory(ObjectPtr theObj)
+{
+ if (theObj) {
+ const std::string aGroup = theObj->groupName();
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(aGroup);
+ if (aHIter != myHistory.end())
+ myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+ if (theObj->groupName() == ModelAPI_Feature::group()) { // clear results group of the feature
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+ if (aFeature->firstResult().get())
+ clearHistory(aFeature->firstResult());
+ }
+ }
+}
+
+void Model_Objects::createHistory(const std::string& theGroupID)
+{
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroupID);
+ if (aHIter == myHistory.end()) {
+ myHistory[theGroupID] = std::vector<ObjectPtr>();
+ std::vector<ObjectPtr>& aResult = myHistory[theGroupID];
+ // iterate the array of references and get feature by feature from the array
+ bool isFeature = theGroupID == ModelAPI_Feature::group();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+ FeaturePtr aFeature = feature(aRefs->Value(a));
+ if (aFeature.get()) {
+ if (isFeature) { // here may be also disabled features
+ if (aFeature->isInHistory()) {
+ aResult.push_back(aFeature);
+ }
+ } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPtr aRes = *aRIter;
+ if (aRes->groupName() != theGroupID) break; // feature have only same group results
+ if (!aRes->isDisabled() && aRes->isInHistory() && !aRes->isConcealed()) {
+ aResult.push_back(*aRIter);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Model_Objects::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+{
+ clearHistory(theObject);
+}
+
+void Model_Objects::updateHistory(const std::string theGroup)
+{
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter = myHistory.find(theGroup);
+ if (aHIter != myHistory.end())
+ myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+}
+
+FeaturePtr Model_Objects::feature(TDF_Label& theLabel) const
+{
+ if (myFeatures.IsBound(theLabel))
+ return myFeatures.Find(theLabel);
+ return FeaturePtr(); // not found
+}
+
+ObjectPtr Model_Objects::object(TDF_Label theLabel)
+{
+ // try feature by label
+ FeaturePtr aFeature = feature(theLabel);
+ if (aFeature)
+ return feature(theLabel);
+ TDF_Label aFeatureLabel = theLabel.Father().Father(); // let's suppose it is result
+ aFeature = feature(aFeatureLabel);
+ if (aFeature) {
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.cbegin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ std::shared_ptr<Model_Data> aResData = std::dynamic_pointer_cast<Model_Data>(
+ (*aRIter)->data());
+ if (aResData->label().Father().IsEqual(theLabel))
+ return *aRIter;
+ }
+ }
+ return FeaturePtr(); // not found
+}
+
+ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex)
+{
+ createHistory(theGroupID);
+ return myHistory[theGroupID][theIndex];
+}
+
+std::shared_ptr<ModelAPI_Object> Model_Objects::objectByName(
+ const std::string& theGroupID, const std::string& theName)
+{
+ createHistory(theGroupID);
+ std::vector<ObjectPtr>& allObjs = myHistory[theGroupID];
+ std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin();
+ for(; anObjIter != allObjs.end(); anObjIter++) {
+ if ((*anObjIter)->data()->name() == theName)
+ return *anObjIter;
+ }
+ // not found
+ return ObjectPtr();
+}
+
+const int Model_Objects::index(std::shared_ptr<ModelAPI_Object> theObject)
+{
+ std::string aGroup = theObject->groupName();
+ createHistory(aGroup);
+ std::vector<ObjectPtr>& allObjs = myHistory[aGroup];
+ std::vector<ObjectPtr>::iterator anObjIter = allObjs.begin(); // iterate to search object
+ for(int anIndex = 0; anObjIter != allObjs.end(); anObjIter++, anIndex++) {
+ if ((*anObjIter) == theObject)
+ return anIndex;
+ }
+ // not found
+ return -1;
+}
+
+int Model_Objects::size(const std::string& theGroupID)
+{
+ createHistory(theGroupID);
+ return myHistory[theGroupID].size();
+}
+
+TDF_Label Model_Objects::featuresLabel() const
+{
+ return myMain.FindChild(TAG_OBJECTS);
+}
+
+void Model_Objects::setUniqueName(FeaturePtr theFeature)
+{
+ if (!theFeature->data()->name().empty())
+ return; // not needed, name is already defined
+ std::string aName; // result
+ // first count all features of such kind to start with index = count + 1
+ int aNumObjects = 0;
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+ for (; aFIter.More(); aFIter.Next()) {
+ if (aFIter.Value()->getKind() == theFeature->getKind())
+ aNumObjects++;
+ }
+ // generate candidate name
+ std::stringstream aNameStream;
+ aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
+ aName = aNameStream.str();
+ // check this is unique, if not, increase index by 1
+ for (aFIter.Initialize(myFeatures); aFIter.More();) {
+ FeaturePtr aFeature = aFIter.Value();
+ bool isSameName = aFeature->data()->name() == aName;
+ if (!isSameName) { // check also results to avoid same results names (actual for Parts)
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ isSameName = (*aRIter)->data()->name() == aName;
+ }
+ }
+ if (isSameName) {
+ aNumObjects++;
+ std::stringstream aNameStream;
+ aNameStream << theFeature->getKind() << "_" << aNumObjects + 1;
+ aName = aNameStream.str();
+ // reinitialize iterator to make sure a new name is unique
+ aFIter.Initialize(myFeatures);
+ } else
+ aFIter.Next();
+ }
+ theFeature->data()->setName(aName);
+}
+
+void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTag)
+{
+ std::shared_ptr<Model_Data> aData(new Model_Data);
+ aData->setLabel(theLab.FindChild(theTag));
+ aData->setObject(theObj);
+ theObj->setDoc(myDoc);
+ theObj->setData(aData);
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
+ if (aFeature) {
+ setUniqueName(aFeature); // must be before "initAttributes" because duplicate part uses name
+ }
+ theObj->initAttributes();
+}
+
+void Model_Objects::synchronizeFeatures(
+ const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
+{
+ Model_Document* anOwner = std::dynamic_pointer_cast<Model_Document>(myDoc).get();
+ if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize
+ return;
+ // after all updates, sends a message that groups of features were created or updated
+ Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+ static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->activateFlushes(false);
+
+ // update all objects by checking are they on labels or not
+ std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
+ TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
+ for (; aLabIter.More(); aLabIter.Next()) {
+ TDF_Label aFeatureLabel = aLabIter.Value()->Label();
+ FeaturePtr aFeature;
+ if (!myFeatures.IsBound(aFeatureLabel)) { // a new feature is inserted
+ // create a feature
+ aFeature = std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get())->createFeature(
+ TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
+ .ToCString(), anOwner);
+ if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure
+ Events_Error::send("Invalid type of object in the document");
+ aLabIter.Value()->Label().ForgetAllAttributes();
+ continue;
+ }
+ // this must be before "setData" to redo the sketch line correctly
+ myFeatures.Bind(aFeatureLabel, aFeature);
+ aNewFeatures.insert(aFeature);
+ initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
+ updateHistory(aFeature);
+
+ // event: model is updated
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
+ } else { // nothing is changed, both iterators are incremented
+ aFeature = myFeatures.Find(aFeatureLabel);
+ aKeptFeatures.insert(aFeature);
+ if (theMarkUpdated) {
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
+ }
+ }
+ }
+ // update results of the features (after features created because they may be connected, like sketch and sub elements)
+ std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
+ TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
+ for (; aLabIter2.More(); aLabIter2.Next()) {
+ TDF_Label aFeatureLabel = aLabIter2.Value()->Label();
+ if (myFeatures.IsBound(aFeatureLabel)) { // a new feature is inserted
+ FeaturePtr aFeature = myFeatures.Find(aFeatureLabel);
+ if (std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature).get())
+ aComposites.push_back(aFeature);
+ updateResults(aFeature);
+ }
+ }
+ std::list<FeaturePtr>::iterator aComposite = aComposites.begin();
+ for(; aComposite != aComposites.end(); aComposite++) {
+ updateResults(*aComposite);
+ }
+
+ // check all features are checked: if not => it was removed
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+ while (aFIter.More()) {
+ if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
+ && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
+ FeaturePtr aFeature = aFIter.Value();
+ // event: model is updated
+ //if (aFeature->isInHistory()) {
+ ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group());
+ //}
+ // results of this feature must be redisplayed (hided)
+ // redisplay also removed feature (used for sketch and AISObject)
+ ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
+ updateHistory(aFeature);
+ aFeature->erase();
+ // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
+ myFeatures.UnBind(aFIter.Key());
+ // reinitialize iterator because unbind may corrupt the previous order in the map
+ aFIter.Initialize(myFeatures);
+ } else
+ aFIter.Next();
+ }
+
+ if (theUpdateReferences) {
+ synchronizeBackRefs();
+ }
+ if (theMarkUpdated) { // this means there is no control what was modified => remove history cash
+ myHistory.clear();
+ }
+
+ anOwner->executeFeatures() = false;
+ aLoop->activateFlushes(true);
+
+ if (theFlush) {
+ aLoop->flush(aCreateEvent);
+ aLoop->flush(aDeleteEvent);
+ aLoop->flush(anUpdateEvent);
+ aLoop->flush(aRedispEvent);
+ aLoop->flush(aToHideEvent);
+ }
+ anOwner->executeFeatures() = true;
+}
+
+void Model_Objects::synchronizeBackRefs()
+{
+ // keeps the concealed flags of result to catch the change and create created/deleted events
+ std::list<std::pair<ResultPtr, bool> > aConcealed;
+ // first cycle: erase all data about back-references
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myFeatures);
+ for(; aFeatures.More(); aFeatures.Next()) {
+ FeaturePtr aFeature = aFeatures.Value();
+ std::shared_ptr<Model_Data> aFData =
+ std::dynamic_pointer_cast<Model_Data>(aFeature->data());
+ if (aFData) {
+ aFData->eraseBackReferences();
+ }
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ std::shared_ptr<Model_Data> aResData =
+ std::dynamic_pointer_cast<Model_Data>((*aRIter)->data());
+ if (aResData) {
+ aConcealed.push_back(std::pair<ResultPtr, bool>(*aRIter, (*aRIter)->isConcealed()));
+ aResData->eraseBackReferences();
+ }
+ }
+ }
+
+ // second cycle: set new back-references: only features may have reference, iterate only them
+ ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+ for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) {
+ FeaturePtr aFeature = aFeatures.Value();
+ std::shared_ptr<Model_Data> aFData =
+ std::dynamic_pointer_cast<Model_Data>(aFeature->data());
+ if (aFData) {
+ std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+ aFData->referencesToObjects(aRefs);
+ std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator
+ aRefsIter = aRefs.begin();
+ for(; aRefsIter != aRefs.end(); aRefsIter++) {
+ std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
+ for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
+ if (*aRefTo) {
+ std::shared_ptr<Model_Data> aRefData =
+ std::dynamic_pointer_cast<Model_Data>((*aRefTo)->data());
+ aRefData->addBackReference(aFeature, aRefsIter->first); // here the Concealed flag is updated
+ }
+ }
+ }
+ }
+ }
+ std::list<std::pair<ResultPtr, bool> >::iterator aCIter = aConcealed.begin();
+ for(; aCIter != aConcealed.end(); aCIter++) {
+ if (aCIter->first->isConcealed() != aCIter->second) { // somethign is changed => produce event
+ if (aCIter->second) { // was concealed become not => creation event
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, anEvent);
+ } else { // was not concealed become concealed => delete event
+ ModelAPI_EventCreator::get()->sendDeleted(myDoc, aCIter->first->groupName());
+ // redisplay for the viewer (it must be disappeared also)
+ static Events_ID EVENT_DISP =
+ Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ ModelAPI_EventCreator::get()->sendUpdated(aCIter->first, EVENT_DISP);
+ }
+ }
+ }
+}
+
+TDF_Label Model_Objects::resultLabel(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex)
+{
+ const std::shared_ptr<Model_Data>& aData =
+ std::dynamic_pointer_cast<Model_Data>(theFeatureData);
+ return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1);
+}
+
+void Model_Objects::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
+ std::shared_ptr<ModelAPI_Result> theResult,
+ const int theResultIndex)
+{
+ theResult->setDoc(myDoc);
+ initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
+ if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name
+ std::stringstream aNewName;
+ aNewName<<theFeatureData->name();
+ if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
+ aNewName<<"_"<<theResultIndex + 1;
+ theResult->data()->setName(aNewName.str());
+ }
+}
+
+std::shared_ptr<ModelAPI_ResultConstruction> Model_Objects::createConstruction(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultConstruction::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultConstruction> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultConstruction>(new Model_ResultConstruction);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultBody> Model_Objects::createBody(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultBody> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultBody>(new Model_ResultBody);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultPart> Model_Objects::createPart(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultPart::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultPart> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultPart>(new Model_ResultPart);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultGroup> Model_Objects::createGroup(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultGroup> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultGroup>(new Model_ResultGroup(theFeatureData));
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_ResultParameter> Model_Objects::createParameter(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex)
+{
+ TDF_Label aLab = resultLabel(theFeatureData, theIndex);
+ TDataStd_Comment::Set(aLab, ModelAPI_ResultParameter::group().c_str());
+ ObjectPtr anOldObject = object(aLab);
+ std::shared_ptr<ModelAPI_ResultParameter> aResult;
+ if (anOldObject) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(anOldObject);
+ }
+ if (!aResult) {
+ aResult = std::shared_ptr<ModelAPI_ResultParameter>(new Model_ResultParameter);
+ storeResult(theFeatureData, aResult, theIndex);
+ }
+ return aResult;
+}
+
+std::shared_ptr<ModelAPI_Feature> Model_Objects::feature(
+ const std::shared_ptr<ModelAPI_Result>& theResult)
+{
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
+ if (aData) {
+ TDF_Label aFeatureLab = aData->label().Father().Father().Father();
+ return feature(aFeatureLab);
+ }
+ return FeaturePtr();
+}
+
+void Model_Objects::updateResults(FeaturePtr theFeature)
+{
+ // for not persistent is will be done by parametric updater automatically
+ //if (!theFeature->isPersistentResult()) return;
+ // check the existing results and remove them if there is nothing on the label
+ std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+ while(aResIter != theFeature->results().cend()) {
+ ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
+ if (aBody) {
+ if (!aBody->data()->isValid()) {
+ // found a disappeared result => remove it
+ theFeature->removeResult(aBody);
+ // start iterate from beginning because iterator is corrupted by removing
+ aResIter = theFeature->results().cbegin();
+ continue;
+ }
+ }
+ aResIter++;
+ }
+ // it may be on undo
+ if (!theFeature->data() || !theFeature->data()->isValid())
+ return;
+ // check that results are presented on all labels
+ int aResSize = theFeature->results().size();
+ TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
+ for(; aLabIter.More(); aLabIter.Next()) {
+ // here must be GUID of the feature
+ int aResIndex = aLabIter.Value().Tag() - 1;
+ ResultPtr aNewBody;
+ if (aResSize <= aResIndex) {
+ TDF_Label anArgLab = aLabIter.Value();
+ Handle(TDataStd_Comment) aGroup;
+ if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
+ if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
+ aNewBody = createBody(theFeature->data(), aResIndex);
+ } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
+ aNewBody = createPart(theFeature->data(), aResIndex);
+ } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
+ theFeature->execute(); // construction shapes are needed for sketch solver
+ break;
+ } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
+ aNewBody = createGroup(theFeature->data(), aResIndex);
+ } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
+ theFeature->attributeChanged("expression"); // just produce a value
+ break;
+ } else {
+ Events_Error::send(std::string("Unknown type of result is found in the document:") +
+ TCollection_AsciiString(aGroup->Get()).ToCString());
+ }
+ }
+ if (aNewBody) {
+ theFeature->setResult(aNewBody, aResIndex);
+ }
+ }
+ }
+}
+
+ResultPtr Model_Objects::findByName(const std::string theName)
+{
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myFeatures);
+ for(; anObjIter.More(); anObjIter.Next()) {
+ FeaturePtr& aFeature = anObjIter.ChangeValue();
+ if (!aFeature.get() || aFeature->isDisabled()) // may be on close
+ continue;
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPtr aRes = *aRIter;
+ if (aRes.get() && aRes->data() && aRes->data()->isValid() && !aRes->isDisabled() &&
+ aRes->data()->name() == theName) {
+ return aRes;
+ }
+ }
+ }
+ // not found
+ return ResultPtr();
+}
+
+FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse)
+{
+ std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
+ if (aData) {
+ TDF_Label aFeatureLabel = aData->label().Father();
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features
+ if (aRefs->Value(a).IsEqual(aFeatureLabel)) {
+ a += theReverse ? -1 : 1;
+ if (a >= aRefs->Lower() && a <= aRefs->Upper())
+ return feature(aRefs->Value(a));
+ break; // finish iiteration: it's last feature
+ }
+ }
+ }
+ }
+ return FeaturePtr(); // not found, last, or something is wrong
+}
+
+FeaturePtr Model_Objects::firstFeature()
+{
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ return feature(aRefs->Value(aRefs->Lower()));
+ }
+ return FeaturePtr(); // no features at all
+}
+
+FeaturePtr Model_Objects::lastFeature()
+{
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ return feature(aRefs->Value(aRefs->Upper()));
+ }
+ return FeaturePtr(); // no features at all
+}
+
+Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
+{
+ return TDF_LabelMapHasher::HashCode(theLab, theUpper);
+
+}
+Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2)
+{
+ return TDF_LabelMapHasher::IsEqual(theLab1, theLab2);
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: Model_Objects.h
+// Created: 15 May 2015
+// Author: Mikhail PONIKAROV
+
+#ifndef Model_Objects_H_
+#define Model_Objects_H_
+
+#include <Model.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_ResultParameter.h>
+
+#include <TDocStd_Document.hxx>
+#include <NCollection_DataMap.hxx>
+#include <TDF_Label.hxx>
+#include <map>
+#include <set>
+#include <vector>
+
+// for TDF_Label map usage
+static Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper);
+static Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2);
+
+/**\class Model_Objects
+ * \ingroup DataModel
+ * \brief Manager of objects of the document. Normally one this class corresponds to
+ * one document and just helper to manage objects (ModelAPI_Objects) inside of the document
+ * on the level of data storage.
+ */
+class Model_Objects
+{
+ public:
+ //! Registers the fieature in the data structure
+ //! \param theFeature feature that must be added to the data structure
+ //! \param theAfterThis the feature will be added after this feature;
+ //! if it is null, the added feature will be the first
+ void addFeature(FeaturePtr theFeature, const FeaturePtr theAfterThis);
+
+ //! Return a list of features, which refers to the feature
+ //! \param theFeature a feature
+ //! \param theRefs a list of reference features
+ //! \param isSendError a flag whether the error message should be send
+ void refsToFeature(FeaturePtr theFeature,
+ std::set<FeaturePtr>& theRefs,
+ const bool isSendError = true);
+
+ //! Removes the feature from the document (with result)
+ //! \param theFeature a removed feature
+ void removeFeature(FeaturePtr theFeature);
+
+ //! Returns the existing feature by the label
+ //! \param theLabel base label of the feature
+ FeaturePtr feature(TDF_Label& theLabel) const;
+
+ //! Returns the existing object: result or feature
+ //! \param theLabel base label of the object
+ ObjectPtr object(TDF_Label theLabel);
+
+ //! Returns the first found object in the group by the object name
+ //! \param theGroupID group that contains an object
+ //! \param theName name of the object to search
+ //! \returns null if such object is not found
+ std::shared_ptr<ModelAPI_Object> objectByName(
+ const std::string& theGroupID, const std::string& theName);
+
+ //! Returns the result by the result name
+ ResultPtr Model_Objects::findByName(const std::string theName);
+
+
+ //! Returns the object index in the group. Object must be visible. Otherwise returns -1.
+ //! \param theObject object of this document
+ //! \returns index started from zero, or -1 if object is invisible or belongs to another document
+ const int index(std::shared_ptr<ModelAPI_Object> theObject);
+
+ //! Returns the feature in the group by the index (started from zero)
+ //! \param theGroupID group that contains a feature
+ //! \param theIndex zero-based index of feature in the group
+ ObjectPtr object(const std::string& theGroupID, const int theIndex);
+
+ //! Returns the number of features in the group
+ int size(const std::string& theGroupID);
+
+ /// Creates a construction cresults
+ std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+ /// Creates a body results
+ std::shared_ptr<ModelAPI_ResultBody> createBody(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+ /// Creates a part results
+ std::shared_ptr<ModelAPI_ResultPart> createPart(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+ /// Creates a group results
+ std::shared_ptr<ModelAPI_ResultGroup> createGroup(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+
+ std::shared_ptr<ModelAPI_ResultParameter> createParameter(
+ const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
+
+ //! Returns a feature by result (owner of result)
+ std::shared_ptr<ModelAPI_Feature>
+ feature(const std::shared_ptr<ModelAPI_Result>& theResult);
+
+ //! Sets the owner of this manager
+ void setOwner(DocumentPtr theDoc) {myDoc = theDoc;}
+
+ //! Returns the owner of this manager
+ DocumentPtr owner() {return myDoc;}
+
+ //! Deletes all managed features wit hemmitting of corresponded signal
+ ~Model_Objects();
+
+ protected:
+
+ //! Returns (creates if needed) the features label
+ TDF_Label featuresLabel() const;
+
+ //! Initializes feature with a unique name in this group (unique name is generated as
+ //! feature type + "_" + index
+ void setUniqueName(FeaturePtr theFeature);
+
+ //! Synchronizes myFeatures list with the updated document
+ //! \param theMarkUpdated causes the "update" event for all features
+ //! \param theUpdateReferences causes the update of back-references
+ //! \param theFlush makes flush all events in the end of all modifications of this method
+ void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
+ const bool theFlush);
+ //! Synchronizes the BackReferences list in Data of Features and Results
+ void synchronizeBackRefs();
+
+ //! Creates manager on the OCAF document main label
+ Model_Objects(TDF_Label theMainLab);
+
+ //! Initializes the data fields of the feature
+ void initData(ObjectPtr theObj, TDF_Label theLab, const int theTag);
+
+ //! Allows to store the result in the data tree of the document (attaches 'data' of result to tree)
+ void storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
+ std::shared_ptr<ModelAPI_Result> theResult,
+ const int theResultIndex = 0);
+
+ //! returns the label of result by index; creates this label if it was not created before
+ TDF_Label resultLabel(const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theResultIndex);
+
+ //! Updates the results list of the feature basing on the current data tree
+ void updateResults(FeaturePtr theFeature);
+
+ /// Internally makes document know that feature was removed or added in history after creation
+ void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+
+ /// Internally makes document know that feature was removed or added in history after creation
+ void updateHistory(const std::string theGroup);
+
+ /// Clears the history arrays related to this object
+ void clearHistory(ObjectPtr theObj);
+
+ /// Creates the history: up to date with the current state
+ void createHistory(const std::string& theGroupID);
+
+ /// Returns to the next (from the history point of view) feature, any: invisible or disabled
+ /// \param theReverse if it is true, iterates in reverced order (next becomes previous)
+ FeaturePtr nextFeature(FeaturePtr theCurrent, const bool theReverse = false);
+ /// Returns to the first (from the history point of view) feature, any: invisible or disabled
+ FeaturePtr firstFeature();
+ /// Returns to the last (from the history point of view) feature, any: invisible or disabled
+ FeaturePtr lastFeature();
+
+ private:
+ TDF_Label myMain; ///< main label of the data storage
+
+ DocumentPtr myDoc; ///< doc,ument, owner of this objects manager: needed for events creation
+
+ /// All managed features (not only in history of OB)
+ /// For optimization mapped by labels
+ NCollection_DataMap<TDF_Label, FeaturePtr> myFeatures;
+
+ /// Map from group id to the array that contains all objects located in history.
+ /// Each array is updated by demand from scratch, by browing all the features in the history.
+ std::map<std::string, std::vector<ObjectPtr> > myHistory;
+
+ friend class Model_Document;
+ friend class Model_Session;
+ friend class Model_Update;
+ friend class Model_AttributeReference;
+ friend class Model_AttributeRefAttr;
+ friend class Model_AttributeRefList;
+};
+
+#endif
#include <ModelAPI_AttributeIntArray.h>
#include <TNaming_Builder.hxx>
#include <TNaming_NamedShape.hxx>
+#include <TNaming_Iterator.hxx>
#include <TDataStd_Name.hxx>
+#include <TDataStd_Integer.hxx>
#include <TopoDS.hxx>
-#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>
#include <TDF_ChildIterator.hxx>
#include <TopTools_MapOfShape.hxx>
}
void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName,
- std::string& theDefault)
+ std::string& theDefault)
{
theSection = "Visualization";
theName = "result_body_color";
theDefault = DEFAULT_COLOR();
}
+bool Model_ResultBody::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
+{
+ bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
+ if (aChanged) { // state is changed, so modifications are needed
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+ if (!aData) // unknown case
+ return aChanged;
+ TDF_Label& aShapeLab = aData->shapeLab();
+
+ std::list<std::pair<TopoDS_Shape, TopoDS_Shape> > aShapePairs; // to store old and new shapes
+ Handle(TNaming_NamedShape) aName;
+ int anEvolution = -1;
+ if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) {
+ anEvolution = (int)(aName->Evolution());
+ for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) {
+ aShapePairs.push_back(std::pair<TopoDS_Shape, TopoDS_Shape>
+ (anIter.OldShape(), anIter.NewShape()));
+ }
+ }
+ // remove old
+ aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID());
+ // create new
+ TNaming_Builder aBuilder(aShapeLab);
+ TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution);
+ std::list<std::pair<TopoDS_Shape, TopoDS_Shape> >::iterator aPairsIter = aShapePairs.begin();
+ for(; aPairsIter != aShapePairs.end(); aPairsIter++) {
+ if (theFlag) { // disabled => make selection
+ aBuilder.Select(aPairsIter->first, aPairsIter->second);
+ } else if (anEvol == TNaming_GENERATED) {
+ aBuilder.Generated(aPairsIter->first, aPairsIter->second);
+ } else if (anEvol == TNaming_MODIFY) {
+ aBuilder.Modify(aPairsIter->first, aPairsIter->second);
+ }
+ }
+ }
+ return aChanged;
+}
+
void Model_ResultBody::store(const std::shared_ptr<GeomAPI_Shape>& theShape)
{
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
return; // null shape inside
aBuilder.Generated(aShape);
- // register name
- if(!aBuilder.NamedShape()->IsEmpty()) {
- Handle(TDataStd_Name) anAttr;
- if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
- std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
- if(!aName.empty()) {
+ // register name
+ if(!aBuilder.NamedShape()->IsEmpty()) {
+ Handle(TDataStd_Name) anAttr;
+ if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+ std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+ if(!aName.empty()) {
std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
- }
- }
- }
+ }
+ }
+ }
}
}
if (aShapeNew.IsNull())
return; // null shape inside
aBuilder.Generated(aShapeBasis, aShapeNew);
- // register name
- if(!aBuilder.NamedShape()->IsEmpty()) {
- Handle(TDataStd_Name) anAttr;
- if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
- std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
- if(!aName.empty()) {
+ // register name
+ if(!aBuilder.NamedShape()->IsEmpty()) {
+ Handle(TDataStd_Name) anAttr;
+ if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+ std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+ if(!aName.empty()) {
std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
- }
- }
- }
+ }
+ }
+ }
}
}
TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
if (aShapeNew.IsNull())
return; // null shape inside
- aBuilder.Modify(aShapeOld, aShapeNew);
+ aBuilder.Modify(aShapeOld, aShapeNew);
}
}
ListOfShape aList;
std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
aRShape->setImpl((new TopoDS_Shape(aRoot)));
- theMS->modified(aRShape, aList);
+ theMS->modified(aRShape, aList);
std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aList.begin(), aLast = aList.end();
for (; anIt != aLast; anIt++) {
TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
}
if (!aRoot.IsSame (aNewShape)) {
builder(theTag)->Modify(aRoot,aNewShape);
- if(!isBuilt)
- buildName(theTag, theName);
- }
+ if(!isBuilt)
+ buildName(theTag, theName);
+ }
}
}
}
}
if (!aRoot.IsSame (aNewShape)) {
builder(theTag)->Generated(aRoot,aNewShape);
- if(!isBuilt)
- buildName(theTag, theName);
- }
+ if(!isBuilt)
+ buildName(theTag, theName);
+ }
}
}
}
//=======================================================================
int getDangleShapes(const TopoDS_Shape& theShapeIn,
- const TopAbs_ShapeEnum theGeneratedFrom,
- TopTools_DataMapOfShapeShape& theDangles)
+ const TopAbs_ShapeEnum theGeneratedFrom,
+ TopTools_DataMapOfShapeShape& theDangles)
{
theDangles.Clear();
TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors;
//=======================================================================
void loadGeneratedDangleShapes(
- const TopoDS_Shape& theShapeIn,
- const TopAbs_ShapeEnum theGeneratedFrom,
- TNaming_Builder * theBuilder)
+ const TopoDS_Shape& theShapeIn,
+ const TopAbs_ShapeEnum theGeneratedFrom,
+ TNaming_Builder * theBuilder)
{
TopTools_DataMapOfShapeShape dangles;
if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return;
TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles);
for (; itr.More(); itr.Next())
- theBuilder->Generated(itr.Key(), itr.Value());
+ theBuilder->Generated(itr.Key(), itr.Value());
}
//=======================================================================
void Model_ResultBody::loadNextLevels(std::shared_ptr<GeomAPI_Shape> theShape,
- const std::string& theName, int& theTag)
+ const std::string& theName, int& theTag)
{
if(theShape->isNull()) return;
TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
if (aShape.ShapeType() == TopAbs_SOLID) {
TopExp_Explorer expl(aShape, TopAbs_FACE);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) {
// load faces and all the free edges
if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) {
TopExp_Explorer expl(aShape, TopAbs_FACE);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ }
TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces;
TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces);
for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++)
- {
+ {
const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i);
if (aLL.Extent() < 2) {
- if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
+ if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i))))
continue;
- builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
+ builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
} else {
- TopTools_ListIteratorOfListOfShape anIter(aLL);
- const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
- anIter.Next();
- if(aFace.IsEqual(anIter.Value())) {
- builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- }
- }
+ TopTools_ListIteratorOfListOfShape anIter(aLL);
+ const TopoDS_Face& aFace = TopoDS::Face(anIter.Value());
+ anIter.Next();
+ if(aFace.IsEqual(anIter.Value())) {
+ builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i));
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ }
+ }
} else if (aShape.ShapeType() == TopAbs_WIRE) {
TopTools_IndexedMapOfShape Edges;
BRepTools::Map3DEdges(aShape, Edges);
if (Edges.Extent() == 1) {
- builder(++theTag)->Generated(Edges.FindKey(1));
+ builder(++theTag)->Generated(Edges.FindKey(1));
TopExp_Explorer expl(aShape, TopAbs_VERTEX);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- } else {
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ } else {
TopExp_Explorer expl(aShape, TopAbs_EDGE);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
// and load generated vertices.
TopTools_DataMapOfShapeShape generated;
if (getDangleShapes(aShape, TopAbs_EDGE, generated))
- {
- TNaming_Builder* pBuilder = builder(theTag++);
- loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);
- }
- }
+ {
+ TNaming_Builder* pBuilder = builder(theTag++);
+ loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder);
+ }
+ }
} else if (aShape.ShapeType() == TopAbs_EDGE) {
TopExp_Explorer expl(aShape, TopAbs_VERTEX);
for (; expl.More(); expl.Next()) {
- builder(theTag)->Generated(expl.Current());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(expl.Current());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
}
//=======================================================================
int findAmbiguities(const TopoDS_Shape& theShapeIn,
- TopTools_ListOfShape& theList)
+ TopTools_ListOfShape& theList)
{
int aNumEdges(0);
theList.Clear();
for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) {
const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i);
const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i);
- aMap1.Clear();
+ aMap1.Clear();
TopTools_ListIteratorOfListOfShape it(ancestors1);
- for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
- for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
- if (i == j) continue;
+ for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1
+ for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) {
+ if (i == j) continue;
const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j);
const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j);
- if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
- int aNum (ancestors2.Extent());
- TopTools_ListIteratorOfListOfShape it(ancestors2);
- for(;it.More();it.Next())
- if(aMap1.Contains(it.Value())) aNum--;
- if(aNum == 0) {
- if(aMap2.Add(aKeyEdge1))
- aKeyList.Append(aKeyEdge1);
- if(aMap2.Add(aKeyEdge2))
- aKeyList.Append(aKeyEdge2);
- }
- }
- } // at the end ==> List of edges to be named in addition
+ if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) {
+ int aNum (ancestors2.Extent());
+ TopTools_ListIteratorOfListOfShape it(ancestors2);
+ for(;it.More();it.Next())
+ if(aMap1.Contains(it.Value())) aNum--;
+ if(aNum == 0) {
+ if(aMap2.Add(aKeyEdge1))
+ aKeyList.Append(aKeyEdge1);
+ if(aMap2.Add(aKeyEdge2))
+ aKeyList.Append(aKeyEdge2);
+ }
+ }
+ } // at the end ==> List of edges to be named in addition
}
aNumEdges = aKeyList.Extent();
if(aNumEdges)
- theList.Assign(aKeyList);
+ theList.Assign(aKeyList);
return aNumEdges;
}
//=======================================================================
void Model_ResultBody::loadFirstLevel(
- std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
+ std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
{
if(theShape->isNull()) return;
TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
TopoDS_Iterator itr(aShape);
for (; itr.More(); itr.Next(),theTag++) {
- builder(theTag)->Generated(itr.Value());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- if(!theName.empty()) buildName(theTag, aName);
+ builder(theTag)->Generated(itr.Value());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ if(!theName.empty()) buildName(theTag, aName);
if (itr.Value().ShapeType() == TopAbs_COMPOUND ||
- itr.Value().ShapeType() == TopAbs_COMPSOLID)
- {
- std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
+ itr.Value().ShapeType() == TopAbs_COMPSOLID)
+ {
+ std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
itrShape->setImpl(new TopoDS_Shape(itr.Value()));
- loadFirstLevel(itrShape, theName, theTag);
+ loadFirstLevel(itrShape, theName, theTag);
} else {
- std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
+ std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
itrShape->setImpl(new TopoDS_Shape(itr.Value()));
- loadNextLevels(itrShape, theName, theTag);
- }
+ loadNextLevels(itrShape, theName, theTag);
+ }
}
} else {
std::shared_ptr<GeomAPI_Shape> itrShape(new GeomAPI_Shape());
itrShape->setImpl(new TopoDS_Shape(aShape));
- loadNextLevels(itrShape, theName, theTag);
+ loadNextLevels(itrShape, theName, theTag);
}
TopTools_ListOfShape aList;
if(findAmbiguities(aShape, aList)) {
- TopTools_ListIteratorOfListOfShape it(aList);
+ TopTools_ListIteratorOfListOfShape it(aList);
for (; it.More(); it.Next(),theTag++) {
- builder(theTag)->Generated(it.Value());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- }
+ builder(theTag)->Generated(it.Value());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ }
}
}
//=======================================================================
void Model_ResultBody::loadDisconnectedEdges(
- std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
+ std::shared_ptr<GeomAPI_Shape> theShape, const std::string& theName, int& theTag)
{
if(theShape->isNull()) return;
TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
Standard_Boolean faceIsNew = Standard_True;
TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge));
for (; itrF.More(); itrF.Next()) {
- if (itrF.Value().IsSame(aFace)) {
- faceIsNew = Standard_False;
- break;
- }
- }
+ if (itrF.Value().IsSame(aFace)) {
+ faceIsNew = Standard_False;
+ break;
+ }
+ }
if (faceIsNew)
- edgeNaborFaces.ChangeFind(anEdge).Append(aFace);
- }
+ edgeNaborFaces.ChangeFind(anEdge).Append(aFace);
+ }
}
-/* TopTools_IndexedDataMapOfShapeListOfShape aDM;
+ /* TopTools_IndexedDataMapOfShapeListOfShape aDM;
TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, aDM);
for(int i=1; i <= aDM.Extent(); i++) {
- if(aDM.FindFromIndex(i).Extent() > 1) continue;
- if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i))))
- continue;
- builder(theTag)->Generated(aDM.FindKey(i));
- TCollection_AsciiString aStr(theTag);
- std::string aName = theName + aStr.ToCString();
- buildName(theTag, aName);
-#ifdef DEB_IMPORT
- aName += + ".brep";
- BRepTools::Write(aDM.FindKey(i), aName.c_str());
-#endif
- theTag++;
+ if(aDM.FindFromIndex(i).Extent() > 1) continue;
+ if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i))))
+ continue;
+ builder(theTag)->Generated(aDM.FindKey(i));
+ TCollection_AsciiString aStr(theTag);
+ std::string aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ #ifdef DEB_IMPORT
+ aName += + ".brep";
+ BRepTools::Write(aDM.FindKey(i), aName.c_str());
+ #endif
+ theTag++;
}
-*/
+ */
TopTools_MapOfShape anEdgesToDelete;
TopExp_Explorer anEx(aShape,TopAbs_EDGE);
std::string aName;
if (aList1.Extent()<2) continue;
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces);
for (; itr.More(); itr.Next()) {
- TopoDS_Shape anEdge2 = itr.Key();
- if(anEdgesToDelete.Contains(anEdge2)) continue;
- if (anEdge1.IsSame(anEdge2)) continue;
- const TopTools_ListOfShape& aList2 = itr.Value();
- // compare lists of the neighbour faces of edge1 and edge2
- if (aList1.Extent() == aList2.Extent()) {
- Standard_Integer aMatches = 0;
- for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
- for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
- if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
- if (aMatches == aList1.Extent()) {
- aC0=Standard_True;
- builder(theTag)->Generated(anEdge2);
- anEdgesToDelete.Add(anEdge2);
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
- }
- }
+ TopoDS_Shape anEdge2 = itr.Key();
+ if(anEdgesToDelete.Contains(anEdge2)) continue;
+ if (anEdge1.IsSame(anEdge2)) continue;
+ const TopTools_ListOfShape& aList2 = itr.Value();
+ // compare lists of the neighbour faces of edge1 and edge2
+ if (aList1.Extent() == aList2.Extent()) {
+ Standard_Integer aMatches = 0;
+ for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next())
+ for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next())
+ if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++;
+ if (aMatches == aList1.Extent()) {
+ aC0=Standard_True;
+ builder(theTag)->Generated(anEdge2);
+ anEdgesToDelete.Add(anEdge2);
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
+ }
+ }
TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete);
for(;itDelete.More();itDelete.Next())
- edgeNaborFaces.UnBind(itDelete.Key());
+ edgeNaborFaces.UnBind(itDelete.Key());
edgeNaborFaces.UnBind(anEdge1);
- }
+ }
if (aC0) {
- builder(theTag)->Generated(anEdge1);
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(anEdge1);
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
}
for (; itr.More(); itr.Next()) {
const TopTools_ListOfShape& naborEdges = itr.Value();
if (naborEdges.Extent() < 2) {
- builder(theTag)->Generated(itr.Key());
- TCollection_AsciiString aStr(theTag);
- aName = theName + aStr.ToCString();
- buildName(theTag, aName);
- theTag++;
- }
+ builder(theTag)->Generated(itr.Key());
+ TCollection_AsciiString aStr(theTag);
+ aName = theName + aStr.ToCString();
+ buildName(theTag, aName);
+ theTag++;
+ }
}
}
/// Request for initialization of data model of the result: adding all attributes
virtual void initAttributes();
- // Retuns the parameters of color definition in the resources config manager
+ /// Returns the parameters of color definition in the resources config manager
MODEL_EXPORT virtual void colorConfigInfo(std::string& theSection, std::string& theName,
std::string& theDefault);
+ /// Disables the result body: keeps the resulting shape as selection, but erases the underlaying
+ /// naming data structure if theFlag if false. Or restores everything on theFlag is true.
+ MODEL_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
+ const bool theFlag);
+
/// Stores the shape (called by the execution method).
MODEL_EXPORT virtual void store(const std::shared_ptr<GeomAPI_Shape>& theShape);
/// builds name for the shape kept at the specified tag
void buildName(const int theTag, const std::string& theName);
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
/// Makes a body on the given feature
Model_ResultConstruction();
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
/// Makes a body on the given feature data
Model_ResultGroup(std::shared_ptr<ModelAPI_Data> theOwnerData);
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
protected:
Model_ResultParameter();
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
/// Returns true if document is activated (loaded into the memory)
virtual bool isActivated();
- friend class Model_Document;
+ friend class Model_Objects;
};
#endif
#include <ModelAPI_Plugin.h>
#include <Model_Data.h>
#include <Model_Document.h>
+#include <Model_Objects.h>
#include <Model_Application.h>
#include <Model_Events.h>
#include <Model_Validator.h>
if (aDoc.get()) {
bool aWasChecked = myCheckTransactions;
setCheckTransactions(false);
- aDoc->synchronizeFeatures(false, true, true);
+ aDoc->objects()->synchronizeFeatures(false, true, true);
if (aWasChecked)
setCheckTransactions(true);
}
aRT->SetRelocation(aSourceRoot, aTargetRoot);
TDF_CopyTool::Copy(aDS, aRT);
- aNew->synchronizeFeatures(false, true, true);
+ aNew->objects()->synchronizeFeatures(false, true, true);
return aNew;
}
FeaturePtr createFeature(std::string theFeatureID, Model_Document* theDocOwner);
friend class Model_Document;
+ friend class Model_Objects;
};
#endif
#include <Model_Update.h>
#include <Model_Document.h>
#include <Model_Data.h>
+#include <Model_Objects.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Document.h>
{
std::set<FeaturePtr> alreadyProcessed; // features that are processed before others
// all features one by one
- for (int aFIndex = 0; aFIndex < theDoc->size(ModelAPI_Feature::group(), true); aFIndex++) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
- theDoc->object(ModelAPI_Feature::group(), aFIndex, true));
- if (aFeature && alreadyProcessed.find(aFeature) == alreadyProcessed.end()) {
+ Model_Objects* anObjs = std::dynamic_pointer_cast<Model_Document>(theDoc)->objects();
+ if (!anObjs) return;
+ FeaturePtr aFeatureIter = anObjs->firstFeature();
+ for (; aFeatureIter.get(); aFeatureIter = anObjs->nextFeature(aFeatureIter)) {
+ if (aFeatureIter && alreadyProcessed.find(aFeatureIter) == alreadyProcessed.end()) {
// update selection and parameters attributes first, before sub-features analysis (sketch plane)
- updateArguments(aFeature);
+ updateArguments(aFeatureIter);
// composite feature must be executed after sub-features execution
CompositeFeaturePtr aComposite =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureIter);
if (aComposite) {
// number of subs can be changed in execution: like fillet
for(int a = 0; a < aComposite->numberOfSubs(); a++) {
}
}
- updateFeature(aFeature);
+ updateFeature(aFeatureIter);
// update the document results recursively
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeatureIter->results();
std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
for (; aRIter != aResults.cend(); aRIter++) {
ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
if (aPart.get()) {
- if (aPart->isActivated()) {
+ if (!aPart->isDisabled() && aPart->isActivated()) {
updateInDoc(aPart->partDoc());
}
}
//! Returns the object in the group by the index (started from zero)
//! \param theGroupID group that contains an object
//! \param theIndex zero-based index of feature in the group
- //! \param theHidden if it is true, it counts also the features that are not in tree
virtual std::shared_ptr<ModelAPI_Object> object(const std::string& theGroupID,
- const int theIndex,
- const bool theHidden = false) = 0;
+ const int theIndex) = 0;
//! Returns the first found object in the group by the object name
//! \param theGroupID group that contains an object
virtual const int index(std::shared_ptr<ModelAPI_Object> theObject) = 0;
//! Returns the number of objects in the group of objects
- //! If theHidden is true, it counts also the features that are not in tree
- virtual int size(const std::string& theGroupID, const bool theHidden = false) = 0;
+ virtual int size(const std::string& theGroupID) = 0;
//! Returns the feature that is currently edited in this document, normally
//! this is the latest created feature
MODELAPI_EXPORT ModelAPI_Document();
/// Internally makes document know that feature was removed or added in history after creation
- MODELAPI_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject) = 0;
+ MODELAPI_EXPORT virtual void updateHistory(const std::shared_ptr<ModelAPI_Object> theObject) = 0;
+ /// Internally makes document know that feature was removed or added in history after creation
+ MODELAPI_EXPORT virtual void updateHistory(const std::string theGroup) = 0;
friend class ModelAPI_Object; // to add or remove from the history
+ friend class ModelAPI_Result; // to add or remove from the history
};
//! Pointer on document object
void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult)
{
- if (firstResult() == theResult) { // just updated
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
- return;
- }
- // created
- while (!myResults.empty()) { // remove one by one with messages
- std::shared_ptr<ModelAPI_Result> aRes = *(myResults.begin());
- myResults.erase(myResults.begin());
- ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName());
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static Events_ID EVENT_UPD = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+
+ if (firstResult() == theResult) {
+ // nothing to change
+ } else if (!myResults.empty()) { // all except first become disabled
+ std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
+ *aResIter = theResult;
+ aECreator->sendUpdated(theResult, EVENT_UPD);
+ for(aResIter++; aResIter != myResults.end(); aResIter++) {
+ (*aResIter)->setDisabled((*aResIter), true);
+ }
+ } else {
+ myResults.push_back(theResult);
}
- myResults.push_back(theResult);
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
- // Create event for first Feature
- Events_Loop::loop()->flush(anEvent);
+ // in any case result decomes enabled
+ theResult->setDisabled(theResult, false);
}
void ModelAPI_Feature::setResult(const std::shared_ptr<ModelAPI_Result>& theResult,
}
if (aResIter == myResults.end()) { // append
myResults.push_back(theResult);
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
- // Create event for first Feature, send it to make "created" earlier than "updated"
- // VSV: Commenting out of this statement causes problems with circle operation for example
- Events_Loop::loop()->flush(anEvent);
} else { // update
*aResIter = theResult;
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, anEvent);
}
+ theResult->setDisabled(theResult, false);
}
void ModelAPI_Feature::removeResult(const std::shared_ptr<ModelAPI_Result>& theResult)
{
- std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
- for(; aResIter != myResults.end(); aResIter++) {
- ResultPtr aRes = *aResIter;
- if (aRes == theResult) {
- std::string aGroup = aRes->groupName();
- aRes->data()->erase();
- myResults.erase(aResIter);
-
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
- ModelAPI_EventCreator::get()->sendDeleted(document(), aGroup);
- aECreator->sendUpdated(aRes, EVENT_DISP);
- break;
- }
- }
+ theResult->setDisabled(theResult, true);
}
void ModelAPI_Feature::removeResults(const int theSinceIndex)
{
- if (theSinceIndex == 0) {
- eraseResults();
- return;
- }
-
std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
for(int anIndex = 0; anIndex < theSinceIndex && aResIter != myResults.end(); anIndex++)
aResIter++;
std::list<std::shared_ptr<ModelAPI_Result> >::iterator aNextIter = aResIter;
for(; aNextIter != myResults.end(); aNextIter++) {
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
- ModelAPI_EventCreator::get()->sendDeleted(document(), (*aNextIter)->groupName());
- aECreator->sendUpdated(*aNextIter, EVENT_DISP);
+ (*aNextIter)->setDisabled(*aNextIter, true); // just disable results
}
- myResults.erase(aResIter, myResults.end());
}
void ModelAPI_Feature::eraseResults()
{
- if (!myResults.empty()) {
- static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
-
- std::list<std::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
- for(; aResIter != myResults.end(); aResIter++) {
- (*aResIter)->data()->erase();
- ModelAPI_EventCreator::get()->sendDeleted(document(), (*aResIter)->groupName());
- aECreator->sendUpdated(*aResIter, EVENT_DISP);
- }
- myResults.clear();
- // flush it to avoid left presentations after input of invalid arguments (radius=0)
- static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
- Events_Loop::loop()->flush(anEvent);
- Events_Loop::loop()->flush(EVENT_DISP);
- }
+ removeResults(0);
}
const std::string& ModelAPI_Feature::documentToAdd()
{
if (myInHistory != theFlag) {
myInHistory = theFlag;
- myDoc->addToHistory(theObject);
+ myDoc->updateHistory(theObject);
}
}
/// removes all fields from this feature
MODELAPI_EXPORT virtual void erase();
- friend class Model_Document;
+ friend class Model_Objects;
};
ModelAPI_Result::~ModelAPI_Result()
{
+}
+bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
+{
+ if (myIsDisabled != theFlag) {
+ myIsDisabled = theFlag;
+ // this must be before "updated" message send to have history updated for OB update
+ document()->updateHistory(groupName()); // to update the history cash data in the document
+ // generate related events
+ static Events_Loop* aLoop = Events_Loop::loop();
+ static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+ if (myIsDisabled) { // disabled result looks like removed
+ aECreator->sendDeleted(document(), groupName());
+ } else { // un-disabled equals to created
+ static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+ aECreator->sendUpdated(theThis, anEvent, false); // do not group: creation must be immediate
+ }
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aECreator->sendUpdated(theThis, EVENT_DISP, false);
+ return true;
+ }
+ return false;
+}
+
+bool ModelAPI_Result::isDisabled() const
+{
+ return myIsDisabled;
}
+void ModelAPI_Result::setIsConcealed(const bool theValue)
+{
+ if (myIsConcealed != theValue) {
+ myIsConcealed = theValue;
+ if (document().get()) // can be on creation of result
+ document()->updateHistory(groupName()); // to update the history cash data in the document
+ }
+}
+
+
std::shared_ptr<GeomAPI_Shape> ModelAPI_Result::shape()
{
return std::shared_ptr<GeomAPI_Shape>();
class ModelAPI_Result : public ModelAPI_Object
{
bool myIsConcealed; ///< the result is concealed from the data tree (referenced by other objects)
+ bool myIsDisabled; ///< the result is disabled: removed for the user, but keeps the general info
public:
/// Reference to the color of the result.
}
/// Returns true if the result is concealed from the data tree (referenced by other objects)
- inline void setIsConcealed(const bool theValue)
- {
- myIsConcealed = theValue;
- }
+ MODELAPI_EXPORT void setIsConcealed(const bool theValue);
+
+ /// Enables/disables the result. The disabled result does not participate in any calculation
+ /// and visualization: like it was removed. But it keeps the general parameters: colors,
+ /// visibility, etc.
+ /// \param theThis pointer to this object, needed to generate all events if it is neccessary
+ /// \param theFlag makes disabled if it is true
+ /// \returns true if state is really changed
+ MODELAPI_EXPORT virtual bool setDisabled(std::shared_ptr<ModelAPI_Result> theThis,
+ const bool theFlag);
+
+ /// Returns the result is disabled or not.
+ MODELAPI_EXPORT virtual bool isDisabled() const;
// Retuns the parameters of color definition in the resources config manager
virtual void colorConfigInfo(std::string& theSection, std::string& theName,