0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[occt.git] / src / TObj / TObj_TIntSparseArray.cxx
1 // Created on: 2007-03-16
2 // Created by: Michael SAZONOV
3 // Copyright (c) 2007-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
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
25
26 IMPLEMENT_STANDARD_RTTIEXT(TObj_TIntSparseArray,TDF_Attribute)
27
28 //=======================================================================
29 //function : TObj_TIntSparseArray
30 //purpose  : Empty constructor
31 //=======================================================================
32
33 TObj_TIntSparseArray::TObj_TIntSparseArray ()
34 : myVector(100), myOldMap(100), myDoBackup (Standard_True)
35 {
36 }
37
38 //=======================================================================
39 //function : GetID
40 //purpose  :
41 //=======================================================================
42
43 const 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
54 const Standard_GUID& TObj_TIntSparseArray::ID() const
55 {
56   return GetID();
57 }
58
59 //=======================================================================
60 //function : Set
61 //purpose  :
62 //=======================================================================
63
64 Handle(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
81 void TObj_TIntSparseArray::SetValue (const Standard_Size theId,
82                                          const Standard_Integer theValue)
83 {
84   // check that modification is allowed
85   if ( !Label().Data()->IsModificationAllowed() )
86     throw Standard_ImmutableObject("Attribute TObj_TIntSparseArray is changed outside transaction");
87
88   if (theId < 1 || theValue < 1)
89     throw Standard_OutOfRange("TObj_TIntSparseArray::SetValue");
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
126 void TObj_TIntSparseArray::UnsetValue (const Standard_Size theId)
127 {
128   // check that modification is allowed
129   if ( !Label().Data()->IsModificationAllowed() )
130     throw Standard_ImmutableObject("Attribute TObj_TIntSparseArray is changed outside transaction");
131
132   if (theId < 1)
133     throw Standard_OutOfRange("TObj_TIntSparseArray::UnsetValue");
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
164 void 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       {
179         Standard_Size anId = anIt.Key();
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
193 void TObj_TIntSparseArray::backupValue (const Standard_Size theId,
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
214 Handle(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
224 Handle(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
241 void 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     {
254       Standard_Size anId = anIt.Key();
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
269 void 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
285 void 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
299 void 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
312 Standard_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 }