0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / TObj / TObj_TIntSparseArray.cxx
CommitLineData
b311480e 1// Created on: 2007-03-16
2// Created by: Michael SAZONOV
973c2be1 3// Copyright (c) 2007-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
7fd59977 16// The original implementation Copyright: (C) RINA S.p.A
17
18#include <TObj_TIntSparseArray.hxx>
19#include <Standard_GUID.hxx>
20#include <Standard_ImmutableObject.hxx>
21#include <TDF_Data.hxx>
22#include <TDF_AttributeDelta.hxx>
23#include <TDF_DeltaOnModification.hxx>
24
7fd59977 25
92efcf78 26IMPLEMENT_STANDARD_RTTIEXT(TObj_TIntSparseArray,TDF_Attribute)
27
7fd59977 28//=======================================================================
29//function : TObj_TIntSparseArray
30//purpose : Empty constructor
31//=======================================================================
32
33TObj_TIntSparseArray::TObj_TIntSparseArray ()
34: myVector(100), myOldMap(100), myDoBackup (Standard_True)
35{
36}
37
38//=======================================================================
39//function : GetID
40//purpose :
41//=======================================================================
42
43const Standard_GUID& TObj_TIntSparseArray::GetID()
44{
45 static Standard_GUID GInterfaceID ("7016dc0c-b118-4433-8ef3-aecdccc79198");
46 return GInterfaceID;
47}
48
49//=======================================================================
50//function : ID
51//purpose :
52//=======================================================================
53
54const Standard_GUID& TObj_TIntSparseArray::ID() const
55{
56 return GetID();
57}
58
59//=======================================================================
60//function : Set
61//purpose :
62//=======================================================================
63
64Handle(TObj_TIntSparseArray) TObj_TIntSparseArray::Set
65 (const TDF_Label& theLabel)
66{
67 Handle(TObj_TIntSparseArray) aTData;
68 if (! theLabel.FindAttribute( GetID(), aTData))
69 {
70 aTData = new TObj_TIntSparseArray;
71 theLabel.AddAttribute(aTData);
72 }
73 return aTData;
74}
75
76//=======================================================================
77//function : SetValue
78//purpose :
79//=======================================================================
80
d93f7683 81void TObj_TIntSparseArray::SetValue (const Standard_Size theId,
7fd59977 82 const Standard_Integer theValue)
83{
84 // check that modification is allowed
85 if ( !Label().Data()->IsModificationAllowed() )
9775fa61 86 throw Standard_ImmutableObject("Attribute TObj_TIntSparseArray is changed outside transaction");
7fd59977 87
88 if (theId < 1 || theValue < 1)
9775fa61 89 throw Standard_OutOfRange("TObj_TIntSparseArray::SetValue");
7fd59977 90
91 Standard_Integer anOld = AbsentValue;
92 Standard_Boolean isOld = myVector.HasValue(theId);
93 if (isOld)
94 {
95 Standard_Integer& aData = myVector(theId);
96 if (aData == theValue)
97 // no actual modification
98 return;
99 anOld = aData;
100 // set new value
101 aData = theValue;
102 }
103 else
104 {
105 // set the new value
106 myVector.SetValue (theId, theValue);
107 }
108
109 TDF_Label aLabel = Label();
110 if (!aLabel.IsNull())
111 {
112 Handle(TDF_Data) aData = aLabel.Data();
113 Standard_Integer aCurrentTransaction = aData->Transaction();
114 Standard_Integer aMyTransaction = Transaction();
115
116 if (myDoBackup && aMyTransaction < aCurrentTransaction)
117 backupValue(theId, anOld, theValue);
118 }
119}
120
121//=======================================================================
122//function : UnsetValue
123//purpose :
124//=======================================================================
125
d93f7683 126void TObj_TIntSparseArray::UnsetValue (const Standard_Size theId)
7fd59977 127{
128 // check that modification is allowed
129 if ( !Label().Data()->IsModificationAllowed() )
9775fa61 130 throw Standard_ImmutableObject("Attribute TObj_TIntSparseArray is changed outside transaction");
7fd59977 131
132 if (theId < 1)
9775fa61 133 throw Standard_OutOfRange("TObj_TIntSparseArray::UnsetValue");
7fd59977 134
135 Standard_Integer anOld = AbsentValue;
136 Standard_Boolean isOld = myVector.HasValue(theId);
137 if (isOld)
138 {
139 anOld = myVector(theId);
140 // unset the value
141 myVector.UnsetValue(theId);
142 }
143 else
144 // no actual modification
145 return;
146
147 TDF_Label aLabel = Label();
148 if (!aLabel.IsNull())
149 {
150 Handle(TDF_Data) aData = aLabel.Data();
151 Standard_Integer aCurrentTransaction = aData->Transaction();
152 Standard_Integer aMyTransaction = Transaction();
153
154 if (myDoBackup && aMyTransaction < aCurrentTransaction)
155 backupValue(theId, anOld, AbsentValue);
156 }
157}
158
159//=======================================================================
160//function : Clear
161//purpose :
162//=======================================================================
163
164void TObj_TIntSparseArray::Clear ()
165{
166 // backup old values
167 TDF_Label aLabel = Label();
168 if (!aLabel.IsNull())
169 {
170 Handle(TDF_Data) aData = aLabel.Data();
171 Standard_Integer aCurrentTransaction = aData->Transaction();
172 Standard_Integer aMyTransaction = Transaction();
173
174 if (myDoBackup && aMyTransaction < aCurrentTransaction)
175 {
176 TObj_TIntSparseArray_VecOfData::Iterator anIt (myVector);
177 for (; anIt.More(); anIt.Next())
178 {
d93f7683 179 Standard_Size anId = anIt.Key();
7fd59977 180 Standard_Integer aVal = anIt.Value();
181 backupValue(anId, aVal, AbsentValue);
182 }
183 }
184 }
185 myVector.Clear();
186}
187
188//=======================================================================
189//function : backupValue
190//purpose :
191//=======================================================================
192
d93f7683 193void TObj_TIntSparseArray::backupValue (const Standard_Size theId,
7fd59977 194 const Standard_Integer theCurrValue,
195 const Standard_Integer theNewValue)
196{
197 // save the current value if it has not been saved in previous time
198 if ( !myOldMap.IsBound( theId ) )
199 myOldMap.Bind(theId, theCurrValue);
200 else
201 {
202 // if value in Undo is the same as the new one, the item in Undo map may be cleared
203 Standard_Integer aUData = myOldMap.Value(theId);
204 if (aUData == theNewValue)
205 myOldMap.UnBind(theId);
206 }
207}
208
209//=======================================================================
210//function : NewEmpty
211//purpose :
212//=======================================================================
213
214Handle(TDF_Attribute) TObj_TIntSparseArray::NewEmpty () const
215{
216 return new TObj_TIntSparseArray;
217}
218
219//=======================================================================
220//function : BackupCopy
221//purpose : Moves <this> delta into a new other attribute.
222//=======================================================================
223
224Handle(TDF_Attribute) TObj_TIntSparseArray::BackupCopy() const
225{
226 Handle(TObj_TIntSparseArray) aCopy =
227 Handle(TObj_TIntSparseArray)::DownCast(NewEmpty());
228
229 // save delta data in a copy
230 if (!myOldMap.IsEmpty())
231 aCopy->myOldMap.Exchange ( (TObj_TIntSparseArray_MapOfData&)myOldMap );
232
233 return aCopy;
234}
235
236//=======================================================================
237//function : Restore
238//purpose : Restores contents of this with theDelta
239//=======================================================================
240
241void TObj_TIntSparseArray::Restore(const Handle(TDF_Attribute)& theDelta)
242{
243 Handle(TObj_TIntSparseArray) aDelta =
244 Handle(TObj_TIntSparseArray)::DownCast(theDelta);
245 if (aDelta.IsNull())
246 return;
247
248 // restore the values from aDelta->myOldMap
249 if (!aDelta->myOldMap.IsEmpty())
250 {
251 TObj_TIntSparseArray_MapOfData::Iterator anIt (aDelta->myOldMap);
252 for (; anIt.More(); anIt.Next())
253 {
d93f7683 254 Standard_Size anId = anIt.Key();
7fd59977 255 Standard_Integer anOld = anIt.Value();
256 if (anOld == AbsentValue)
257 UnsetValue (anId);
258 else
259 SetValue (anId, anOld);
260 }
261 }
262}
263
264//=======================================================================
265//function : Paste
266//purpose : copy this
267//=======================================================================
268
269void TObj_TIntSparseArray::Paste (const Handle(TDF_Attribute)& theInto,
270 const Handle(TDF_RelocationTable)&) const
271{
272 Handle(TObj_TIntSparseArray) aInto =
273 Handle(TObj_TIntSparseArray)::DownCast(theInto);
274 if(aInto.IsNull())
275 return;
276
277 aInto->myVector.Assign(myVector);
278}
279
280//=======================================================================
281//function : BeforeCommitTransaction
282//purpose : It is called just before Commit or Abort transaction
283//=======================================================================
284
285void TObj_TIntSparseArray::BeforeCommitTransaction()
286{
287 if (!myOldMap.IsEmpty())
288 {
289 Backup();
290 ClearDelta();
291 }
292}
293
294//=======================================================================
295//function : DeltaOnModification
296//purpose : Applies aDelta to <me>
297//=======================================================================
298
299void TObj_TIntSparseArray::DeltaOnModification
300 (const Handle(TDF_DeltaOnModification)& theDelta)
301{
302 // we do not call Backup here, because a backup data is formed inside Restore.
303 // Backup is called rather from BeforeCommitTransaction
304 Restore(theDelta->Attribute());
305}
306
307//=======================================================================
308//function : AfterUndo
309//purpose : After application of a TDF_Delta.
310//=======================================================================
311
312Standard_Boolean TObj_TIntSparseArray::AfterUndo
313 (const Handle(TDF_AttributeDelta)&,
314 const Standard_Boolean)
315{
316 // we must be sure that a delta in <me> is cleared
317 ClearDelta();
318 return Standard_True;
319}