// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#include <TDF_Data.ixx>
+#include <NCollection_IncAllocator.hxx>
+#include <Standard_Dump.hxx>
+#include <Standard_NoMoreObject.hxx>
+#include <Standard_NullObject.hxx>
+#include <Standard_Type.hxx>
+#include <Standard_GUID.hxx>
+#include <NCollection_Array1.hxx>
#include <TCollection_AsciiString.hxx>
-
#include <TDF_Attribute.hxx>
-#include <TDF_AttributeIterator.hxx>
+#include <TDF_AttributeDelta.hxx>
#include <TDF_AttributeIndexedMap.hxx>
+#include <TDF_AttributeIterator.hxx>
#include <TDF_ChildIterator.hxx>
+#include <TDF_Data.hxx>
#include <TDF_Delta.hxx>
-#include <TDF_AttributeDelta.hxx>
#include <TDF_DeltaOnAddition.hxx>
#include <TDF_DeltaOnForget.hxx>
#include <TDF_DeltaOnModification.hxx>
#include <TDF_LabelNode.hxx>
#include <TDF_LabelNodePtr.hxx>
#include <TDF_Tool.hxx>
+#include <TDF_Transaction.hxx>
-#include <Standard_NoMoreObject.hxx>
-#include <Standard_NullObject.hxx>
+typedef NCollection_Array1<Handle(TDF_AttributeDelta)> TDF_Array1OfAttributeIDelta;
-#include <NCollection_IncAllocator.hxx>
+IMPLEMENT_STANDARD_RTTIEXT(TDF_Data,Standard_Transient)
#undef DEB_DELTA_CREATION
#undef TDF_DATA_COMMIT_OPTIMIZED
#ifdef OCCT_DEBUG_DELTA
#define TDF_Data_DebugModified(ACTION) \
- cout<<"After "<<ACTION<<" #"<<myTransaction+1<<", DF "<<this<<" had "<<myNbTouchedAtt<<" attribute(s) touched. Time = "<<myTime<<endl; \
+ std::cout<<"After "<<ACTION<<" #"<<myTransaction+1<<", DF "<<this<<" had "<<myNbTouchedAtt<<" attribute(s) touched. Time = "<<myTime<<std::endl; \
if (!myTransaction) { \
TCollection_AsciiString entry; \
for (TDF_ChildIterator itr(Root(),Standard_True); itr.More(); itr.Next()) { \
const TDF_LabelNode* lnp = itr.Value().myLabelNode; \
if (lnp->AttributesModified() || lnp->MayBeModified()) { \
TDF_Tool::Entry(itr.Value(),entry); \
- cout<<ACTION<<" on "<<entry<<" : flag(s) "; \
- if (lnp->AttributesModified()) cout<<"AttributesModified "; \
- if (lnp->MayBeModified()) cout<<"MayBeModified already set in transaction 0! Please contact TDF developer."; \
- cout<<endl; \
- cout<<itr.Value()<<endl; \
+ std::cout<<ACTION<<" on "<<entry<<" : flag(s) "; \
+ if (lnp->AttributesModified()) std::cout<<"AttributesModified "; \
+ if (lnp->MayBeModified()) std::cout<<"MayBeModified already set in transaction 0! Please contact TDF developer."; \
+ std::cout<<std::endl; \
+ std::cout<<itr.Value()<<std::endl; \
entry.Clear(); \
}}}
#else
{ \
TCollection_AsciiString entry; \
TDF_Tool::Entry(currentAtt->Label(),entry); \
-cout<<"Creation of a DeltaOn"<<DELTATYPE<<" \tat "<<entry<<" \ton "<<currentAtt->DynamicType()<<endl; \
+std::cout<<"Creation of a DeltaOn"<<DELTATYPE<<" \tat "<<entry<<" \ton "<<currentAtt->DynamicType()<<std::endl; \
}
#else
#define TDF_DataDebugDeltaCreation(DELTATYPE)
void TDF_Data::Destroy()
{
AbortUntilTransaction(1);
+ // Forget the Owner attribute from the root label to avoid referencing document before
+ // desctuction of the framework (on custom attributes forget). Don't call ForgetAll because
+ // it may call backup.
+ while(!myRoot->FirstAttribute().IsNull()) {
+ static Handle(TDF_Attribute) anEmpty;
+ Handle(TDF_Attribute) aFirst = myRoot->FirstAttribute();
+ myRoot->RemoveAttribute(anEmpty, aFirst);
+ }
myRoot->Destroy (myLabelNodeAllocator);
myRoot = NULL;
}
if (myTransaction>0) {
if (withDelta) delta = new TDF_Delta();
#ifdef OCCT_DEBUG_DELTA
- cout<<"TDF_Data::Begin Commit #"<<myTransaction<<endl;
+ std::cout<<"TDF_Data::Begin Commit #"<<myTransaction<<std::endl;
#endif
#ifdef TDF_DATA_COMMIT_OPTIMIZED
myNbTouchedAtt = 0;
delta->Validity(myTimes.First(),myTime);
#ifdef OCCT_DEBUG_DELTA
if (myTransaction == 0) {
- cout<<"TDF_Data::Commit generated this delta in t=0:"<<endl;
- delta->Dump(cout);
+ std::cout<<"TDF_Data::Commit generated this delta in t=0:"<<std::endl;
+ delta->Dump(std::cout);
}
#endif
}
#ifdef OCCT_DEBUG_DELTA
else {
if (myTransaction == 0)
- cout<<"TDF_Data::Commit generated NO delta."<<endl;
+ std::cout<<"TDF_Data::Commit generated NO delta."<<std::endl;
}
#endif
}
TDF_AttributeIterator itr1(aLabel, Standard_False);
while (itr1.More()) {
- TDF_Attribute * aPtrCurrentAtt = itr1.Value();
+ Handle(TDF_Attribute) aPtrCurrentAtt = itr1.Value();
itr1.Next();
// currentAtt = itr1.Value();
}
// --------------------------------------------------------- Modified.
else {
+ const TDF_Attribute* anAttrPtr = aPtrCurrentAtt.operator->(); // to avoid ambiguity
TDF_Data_DeltaCreation
("Modification",
- aPtrCurrentAtt->DeltaOnModification(backupAtt));
+ anAttrPtr->DeltaOnModification(backupAtt));
if (aPtrCurrentAtt->myTransaction == backupAtt->myTransaction)
aPtrCurrentAtt->RemoveBackup();
attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
return !aDelta.IsNull() && aDelta->IsApplicable(myTime);
}
-
+//=======================================================================
+//function : FixOrder
+//purpose :
+//=======================================================================
+void TDF_Data::FixOrder(const Handle(TDF_Delta)& theDelta)
+{
+ // make all OnRemoval (which will cause addition of the attribute) are in the end
+ // to do not put two attributes with the same GUID at one label during undo/redo
+ TDF_AttributeDeltaList anOrderedList;
+
+ const TDF_AttributeDeltaList& attList = theDelta->AttributeDeltas();
+ TDF_ListIteratorOfAttributeDeltaList anIt(attList);
+ for (; anIt.More(); anIt.Next()) { // append not-removal
+ Handle(TDF_AttributeDelta) attDelta = anIt.Value();
+ if (!attDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) {
+ anOrderedList.Append(attDelta);
+ }
+ }
+ for (anIt.Initialize(attList); anIt.More(); anIt.Next()) { // append removal
+ Handle(TDF_AttributeDelta) attDelta = anIt.Value();
+ if (attDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) {
+ anOrderedList.Append(attDelta);
+ }
+ }
+ theDelta->ReplaceDeltaList(anOrderedList);
+}
//=======================================================================
//function : Undo
//purpose : Applies a delta to undo actions.
//=======================================================================
-Handle(TDF_Delta) TDF_Data::Undo
-(const Handle(TDF_Delta)& aDelta,
- const Standard_Boolean withDelta)
+Handle(TDF_Delta) TDF_Data::Undo(const Handle(TDF_Delta)& aDelta,
+ const Standard_Boolean withDelta)
{
Handle(TDF_Delta) newDelta;
if (!aDelta.IsNull ()) {
if (aDelta->IsApplicable(myTime)) {
if (withDelta) OpenTransaction();
#ifdef OCCT_DEBUG_DELTA
- cout<<"TDF_Data::Undo applies this delta:"<<endl;
- aDelta->Dump(cout);
+ std::cout<<"TDF_Data::Undo applies this delta:"<<std::endl;
+ aDelta->Dump(std::cout);
#endif
aDelta->BeforeOrAfterApply(Standard_True);
myNotUndoMode = Standard_False;
+ FixOrder(aDelta);
aDelta->Apply ();
myNotUndoMode = Standard_True;
if (withDelta) {
newDelta = CommitTransaction(Standard_True);
newDelta->Validity(aDelta->EndTime(),aDelta->BeginTime());
#ifdef OCCT_DEBUG_DELTA
- cout<<"TDF_Data::Undo, after validity correction, Delta is now available from time \t#"<<newDelta->BeginTime()<<" to time \t#"<<newDelta->EndTime()<<endl;
+ std::cout<<"TDF_Data::Undo, after validity correction, Delta is now available from time \t#"<<newDelta->BeginTime()<<" to time \t#"<<newDelta->EndTime()<<std::endl;
#endif
}
myTime = aDelta->BeginTime();
Standard_OStream& TDF_Data::Dump(Standard_OStream& anOS) const
{
- anOS<<"Dump of a TDF_Data."<<endl;
+ anOS<<"Dump of a TDF_Data."<<std::endl;
anOS<<"Current transaction: "<<myTransaction;
- anOS<<"; Current tick: "<<myTime<<";"<<endl;
+ anOS<<"; Current tick: "<<myTime<<";"<<std::endl;
return anOS;
}
+
+//=======================================================================
+//function : DumpJson
+//purpose :
+//=======================================================================
+void TDF_Data::DumpJson (Standard_OStream& theOStream, Standard_Integer /*theDepth*/) const
+{
+ OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
+
+ TCollection_AsciiString aStrForTDF_Label;
+ TDF_Tool::Entry (myRoot, aStrForTDF_Label);
+ OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aStrForTDF_Label)
+
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTransaction)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNbTouchedAtt)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNotUndoMode)
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTime)
+ for (TColStd_ListOfInteger::Iterator aTimeIt (myTimes); aTimeIt.More(); aTimeIt.Next())
+ {
+ const Standard_Integer aTime = aTimeIt.Value();
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aTime)
+ }
+ OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAllowModification)
+}