Salome HOME
f8eebe405a4bd3140081954fd536f0aafde87240
[modules/shaper.git] / src / Model / Model_AttributeTables.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        Model_AttributeTables.cpp
4 // Created:     14 Nov 2016
5 // Author:      Mikhail Ponikarov
6
7 #include "Model_AttributeTables.h"
8
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_Object.h>
11
12 #include <TColStd_ListIteratorOfListOfInteger.hxx>
13 #include <TDataStd_RealArray.hxx>
14 #include <TDataStd_BooleanArray.hxx>
15 #include <TDataStd_IntegerArray.hxx>
16 #include <TDataStd_ExtStringArray.hxx>
17
18 #include <TColStd_HArray1OfReal.hxx>
19 #include <TColStd_HArray1OfByte.hxx>
20 #include <TColStd_HArray1OfInteger.hxx>
21 #include <TColStd_HArray1OfExtendedString.hxx>
22
23 #include <string>
24
25 // returns the array attribute GUID for the given type
26 #define MY_ARRAY_ID(type) \
27 ((type) == ModelAPI_AttributeTables::DOUBLE ? TDataStd_RealArray::GetID(): \
28 ((type) == ModelAPI_AttributeTables::BOOLEAN ? TDataStd_BooleanArray::GetID(): \
29 ((type) == ModelAPI_AttributeTables::INTEGER? TDataStd_IntegerArray::GetID(): \
30 TDataStd_ExtStringArray::GetID())))
31
32 int Model_AttributeTables::rows()
33 {
34   return myRows;
35 }
36
37 int Model_AttributeTables::columns()
38 {
39   return myCols;
40 }
41
42 int Model_AttributeTables::tables()
43 {
44   return myTables;
45 }
46
47 void Model_AttributeTables::setSize(const int theRows, const int theColumns, const int theTables)
48 {
49   if (theRows != myRows || theColumns != myCols || theTables != myTables) {
50     owner()->data()->sendAttributeUpdated(this);
51     int aSize = myRows * myCols * myTables;
52     int aNewSize = theRows * theColumns * theTables;
53     if (aSize == 0 && aNewSize == 0) {
54       // nothing to do
55     } else if (aNewSize == 0) {
56       // remove old array
57       myLab.ForgetAttribute(MY_ARRAY_ID(myType));
58     } else {
59       // prepare new arrays
60       Handle(TColStd_HArray1OfReal) anOldDouble, aNewDouble =
61         (myType == ModelAPI_AttributeTables::DOUBLE) ?
62         new TColStd_HArray1OfReal(0, aNewSize - 1) : Handle(TColStd_HArray1OfReal)();
63       bool* anOldBool = 0; // an not work with internal arrays because of different indexing
64       Handle(TColStd_HArray1OfByte) aNewBool = (myType == ModelAPI_AttributeTables::BOOLEAN) ?
65         // internal array for boolean has 8 times lower size
66         new TColStd_HArray1OfByte(0, (aNewSize - 1)>>3) : Handle(TColStd_HArray1OfByte)();
67       Handle(TDataStd_BooleanArray) aBoolArray; // an existing array
68       Handle(TColStd_HArray1OfInteger) anOldInt, aNewInt =
69         (myType == ModelAPI_AttributeTables::INTEGER) ?
70         new TColStd_HArray1OfInteger(0, aNewSize - 1) : Handle(TColStd_HArray1OfInteger)();
71       Handle(TColStd_HArray1OfExtendedString) anOldStr, aNewStr =
72         (myType == ModelAPI_AttributeTables::STRING) ?
73         new TColStd_HArray1OfExtendedString(0, aNewSize - 1) :
74         Handle(TColStd_HArray1OfExtendedString)();
75       if (aSize != 0) { // copy the previous values into new positions, otherwise default values
76         Handle(TDF_Attribute) anArray;
77         myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
78         switch(myType) {
79         case ModelAPI_AttributeTables::DOUBLE:
80           anOldDouble = Handle(TDataStd_RealArray)::DownCast(anArray)->Array();
81           break;
82         case ModelAPI_AttributeTables::BOOLEAN: {
83           anOldBool = new bool[aSize];
84           aBoolArray = Handle(TDataStd_BooleanArray)::DownCast(anArray);
85           for(int a = 0; a < aSize; a++)
86             anOldBool[a] = aBoolArray->Value(a);
87           aBoolArray->SetInternalArray(aNewBool);
88           break;
89         }
90         case ModelAPI_AttributeTables::INTEGER:
91           anOldInt = Handle(TDataStd_IntegerArray)::DownCast(anArray)->Array();
92           break;
93         case ModelAPI_AttributeTables::STRING:
94           anOldStr = Handle(TDataStd_ExtStringArray)::DownCast(anArray)->Array();
95           break;
96         }
97       } else if (myType == ModelAPI_AttributeTables::BOOLEAN) {
98         aBoolArray = TDataStd_BooleanArray::Set(myLab, 0, aNewSize - 1);
99       }
100       for(int aTable = 0; aTable < theTables; aTable++) {
101         for(int aColumn = 0; aColumn < theColumns; aColumn++) {
102           for(int aRow = 0; aRow < theRows; aRow++) {
103             int anOldIndex, anIndex = aTable * theRows * theColumns + aRow * theColumns + aColumn;
104             bool aRestore = aTable < myTables && aColumn < myCols && aRow < myRows;
105             if (aRestore)
106               anOldIndex = aTable * myRows * myCols + aRow * myCols + aColumn;
107             switch(myType) {
108             case ModelAPI_AttributeTables::DOUBLE: {
109               aNewDouble->SetValue(anIndex, aRestore ? anOldDouble->Value(anOldIndex) : 0.);
110               break;
111             }
112             case ModelAPI_AttributeTables::BOOLEAN: {
113               aBoolArray->SetValue(anIndex, aRestore ? anOldBool[anOldIndex] : Standard_False);
114               break;
115             }
116             case ModelAPI_AttributeTables::INTEGER: {
117               aNewInt->SetValue(anIndex, aRestore ? anOldInt->Value(anOldIndex) : 0);
118               break;
119             }
120             case ModelAPI_AttributeTables::STRING: {
121               aNewStr->SetValue(anIndex, aRestore ? anOldStr->Value(anOldIndex) : "");
122               break;
123             }
124             }
125           }
126         }
127       }
128       // store the new array
129       switch(myType) {
130       case ModelAPI_AttributeTables::DOUBLE:
131         TDataStd_RealArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewDouble);
132         break;
133       case ModelAPI_AttributeTables::BOOLEAN: // nothing to do: array was set in "else" of restore
134         break;
135       case ModelAPI_AttributeTables::INTEGER:
136         TDataStd_IntegerArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewInt);
137         break;
138       case ModelAPI_AttributeTables::STRING:
139         TDataStd_ExtStringArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewStr);
140         break;
141       }
142     }
143     // store the new sizes
144     myRows = theRows;
145     myCols = theColumns;
146     myTables = theTables;
147     myProp->Clear();
148     myProp->Append(int(myType)); // default
149     myProp->Append(myTables);
150     myProp->Append(myRows);
151     myProp->Append(myCols);
152     owner()->data()->sendAttributeUpdated(this);
153   }
154 }
155
156 void Model_AttributeTables::setType(ModelAPI_AttributeTables::ValueType theType)
157 {
158   if (myType != theType) {
159     // remove the old attr
160     int aSize = myRows * myCols * myTables;
161     if (aSize != 0) {
162       myLab.ForgetAttribute(MY_ARRAY_ID(myType));
163       myType = theType;
164       int aTables = myTables;
165       myTables = 0; // to let setSize know that there is no old array
166       setSize(myRows, myCols, aTables);
167     } else {
168       myType = theType;
169       owner()->data()->sendAttributeUpdated(this);
170     }
171   }
172 }
173
174 const ModelAPI_AttributeTables::ValueType& Model_AttributeTables::type() const
175 {
176   return myType;
177 }
178
179 void Model_AttributeTables::setValue(const ModelAPI_AttributeTables::Value theValue,
180   const int theRow, const int theColumn, const int theTable)
181 {
182   int anIndex = theTable * myRows * myCols + theRow * myCols + theColumn;
183   Handle(TDF_Attribute) anArray;
184   myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
185   switch(myType) {
186   case ModelAPI_AttributeTables::DOUBLE: {
187     Handle(TDataStd_RealArray)::DownCast(anArray)->SetValue(anIndex, theValue.myDouble);
188     break;
189   }
190   case ModelAPI_AttributeTables::BOOLEAN: {
191     Handle(TDataStd_BooleanArray)::DownCast(anArray)->SetValue(anIndex, theValue.myBool);
192     break;
193   }
194   case ModelAPI_AttributeTables::INTEGER: {
195     Handle(TDataStd_IntegerArray)::DownCast(anArray)->SetValue(anIndex, theValue.myInt);
196     break;
197   }
198   case ModelAPI_AttributeTables::STRING: {
199     Handle(TDataStd_ExtStringArray)::DownCast(anArray)->SetValue(anIndex, theValue.myStr.c_str());
200     break;
201   }
202   }
203   owner()->data()->sendAttributeUpdated(this);
204 }
205
206 ModelAPI_AttributeTables::Value Model_AttributeTables::value(
207   const int theRow, const int theColumn, const int theTable)
208 {
209   ModelAPI_AttributeTables::Value aResult;
210   int anIndex = theTable * myRows * myCols + theRow * myCols + theColumn;
211   Handle(TDF_Attribute) anArray;
212   myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
213   switch(myType) {
214   case ModelAPI_AttributeTables::DOUBLE: {
215     aResult.myDouble = Handle(TDataStd_RealArray)::DownCast(anArray)->Value(anIndex);
216     break;
217   }
218   case ModelAPI_AttributeTables::BOOLEAN: {
219     aResult.myBool = Handle(TDataStd_BooleanArray)::DownCast(anArray)->Value(anIndex) ==
220       Standard_True;
221     break;
222   }
223   case ModelAPI_AttributeTables::INTEGER: {
224     aResult.myInt = Handle(TDataStd_IntegerArray)::DownCast(anArray)->Value(anIndex);
225     break;
226   }
227   case ModelAPI_AttributeTables::STRING: {
228     aResult.myStr = TCollection_AsciiString(Handle(TDataStd_ExtStringArray)::DownCast(anArray)->
229       Value(anIndex)).ToCString();
230     break;
231   }
232   }
233   return aResult;
234 }
235
236 std::string Model_AttributeTables::valueStr(
237     const int theRow, const int theColumn, const int theTable)
238 {
239   std::ostringstream aStr;
240   switch(myType) {
241   case ModelAPI_AttributeTables::DOUBLE:
242     aStr<<value(theRow, theColumn, theTable).myDouble;
243     break;
244   case ModelAPI_AttributeTables::BOOLEAN:
245     aStr<<(value(theRow, theColumn, theTable).myBool ? "True" :"False");
246     break;
247   case ModelAPI_AttributeTables::INTEGER:
248     aStr<<value(theRow, theColumn, theTable).myInt;
249     break;
250   case ModelAPI_AttributeTables::STRING:
251     aStr<<value(theRow, theColumn, theTable).myStr;
252     break;
253   }
254   return aStr.str();
255 }
256
257 //==================================================================================================
258 Model_AttributeTables::Model_AttributeTables(TDF_Label& theLabel)
259 {
260   myLab = theLabel;
261   reinit();
262 }
263
264 void Model_AttributeTables::reinit()
265 {
266   // check the attribute could be already presented in this doc (after load document)
267   myIsInitialized =
268     myLab.FindAttribute(TDataStd_IntegerList::GetID(), myProp) == Standard_True;
269   if (!myIsInitialized) {
270     myProp = TDataStd_IntegerList::Set(myLab);
271     myProp->Append(int(Model_AttributeTables::DOUBLE)); // default
272     myProp->Append(0);
273     myProp->Append(0);
274     myProp->Append(0);
275   }
276   TColStd_ListIteratorOfListOfInteger aListIter(myProp->List());
277   myType = ModelAPI_AttributeTables::ValueType(aListIter.Value());
278   aListIter.Next();
279   myTables = aListIter.Value();
280   aListIter.Next();
281   myRows = aListIter.Value();
282   aListIter.Next();
283   myCols = aListIter.Value();
284 }