Salome HOME
Issue #1865: Create a field
[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       Handle(TColStd_HArray1OfByte) anOldBool, aNewBool =
64         (myType == ModelAPI_AttributeTables::BOOLEAN) ?
65         new TColStd_HArray1OfByte(0, aNewSize - 1) : Handle(TColStd_HArray1OfByte)();
66       Handle(TColStd_HArray1OfInteger) anOldInt, aNewInt =
67         (myType == ModelAPI_AttributeTables::INTEGER) ? 
68         new TColStd_HArray1OfInteger(0, aNewSize - 1) : Handle(TColStd_HArray1OfInteger)();
69       Handle(TColStd_HArray1OfExtendedString) anOldStr, aNewStr =
70         (myType == ModelAPI_AttributeTables::STRING) ? 
71         new TColStd_HArray1OfExtendedString(0, aNewSize - 1) :
72         Handle(TColStd_HArray1OfExtendedString)();
73       if (aSize != 0) { // copy the previous values into new positions, otherwise default values
74         Handle(TDF_Attribute) anArray;
75         myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
76         switch(myType) {
77         case ModelAPI_AttributeTables::DOUBLE:
78           anOldDouble = Handle(TDataStd_RealArray)::DownCast(anArray)->Array();
79           break;
80         case ModelAPI_AttributeTables::BOOLEAN:
81           anOldBool = Handle(TDataStd_BooleanArray)::DownCast(anArray)->InternalArray();
82           break;
83         case ModelAPI_AttributeTables::INTEGER:
84           anOldInt = Handle(TDataStd_IntegerArray)::DownCast(anArray)->Array();
85           break;
86         case ModelAPI_AttributeTables::STRING:
87           anOldStr = Handle(TDataStd_ExtStringArray)::DownCast(anArray)->Array();
88           break;
89         }
90       }
91       for(int aTable = 0; aTable < theTables; aTable++) {
92         for(int aColumn = 0; aColumn < theColumns; aColumn++) {
93           for(int aRow = 0; aRow < theRows; aRow++) {
94             int anOldIndex, anIndex = aTable * theRows * theColumns + aRow * theColumns + aColumn;
95             bool aRestore = aTable < myTables && aColumn < myCols && aRow < myRows;
96             if (aRestore)
97               anOldIndex = aTable * myRows * myCols + aRow * myCols + aColumn;
98             switch(myType) {
99             case ModelAPI_AttributeTables::DOUBLE: {
100               aNewDouble->SetValue(anIndex, aRestore ? anOldDouble->Value(anOldIndex) : 0.);
101               break;
102             }
103             case ModelAPI_AttributeTables::BOOLEAN: {
104               aNewBool->SetValue(anIndex, aRestore ? anOldBool->Value(anOldIndex) : Standard_False);
105               break;
106             }
107             case ModelAPI_AttributeTables::INTEGER: {
108               aNewInt->SetValue(anIndex, aRestore ? anOldInt->Value(anOldIndex) : 0);
109               break;
110             }
111             case ModelAPI_AttributeTables::STRING: {
112               aNewStr->SetValue(anIndex, aRestore ? anOldStr->Value(anOldIndex) : "");
113               break;
114             }
115             }
116           }
117         }
118       }
119       // store the new array
120       switch(myType) {
121       case ModelAPI_AttributeTables::DOUBLE:
122         TDataStd_RealArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewDouble);
123         break;
124       case ModelAPI_AttributeTables::BOOLEAN:
125         TDataStd_BooleanArray::Set(myLab, 0, aNewSize - 1)->SetInternalArray(aNewBool);
126         break;
127       case ModelAPI_AttributeTables::INTEGER:
128         TDataStd_IntegerArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewInt);
129         break;
130       case ModelAPI_AttributeTables::STRING:
131         TDataStd_ExtStringArray::Set(myLab, 0, aNewSize - 1)->ChangeArray(aNewStr);
132         break;
133       }
134     }
135     // store the new sizes
136     myRows = theRows;
137     myCols = theColumns;
138     myTables = theTables;
139     myProp->Clear();
140     myProp->Append(int(myType)); // default
141     myProp->Append(myTables);
142     myProp->Append(myRows);
143     myProp->Append(myCols);
144     owner()->data()->sendAttributeUpdated(this);
145   }
146 }
147
148 void Model_AttributeTables::setType(ModelAPI_AttributeTables::ValueType theType)
149 {
150   if (myType != theType) {
151     // remove the old attr
152     int aSize = myRows * myCols * myTables;
153     if (aSize != 0) {
154       myLab.ForgetAttribute(MY_ARRAY_ID(theType));
155       myType = theType;
156       int aTables = myTables;
157       myTables = 0; // to let setSize know that there is no old array 
158       setSize(myRows, myCols, aTables);
159     } else {
160       myType = theType;
161       owner()->data()->sendAttributeUpdated(this);
162     }
163   }
164 }
165
166 const ModelAPI_AttributeTables::ValueType& Model_AttributeTables::type() const
167 {
168   return myType;
169 }
170
171 void Model_AttributeTables::setValue(const ModelAPI_AttributeTables::Value theValue,
172   const int theRow, const int theColumn, const int theTable)
173 {
174   int anIndex = theTable * myRows * myCols + theRow * myCols + theColumn;
175   Handle(TDF_Attribute) anArray;
176   myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
177   switch(myType) {
178   case ModelAPI_AttributeTables::DOUBLE: {
179     Handle(TDataStd_RealArray)::DownCast(anArray)->SetValue(anIndex, theValue.myDouble);
180     break;
181   }
182   case ModelAPI_AttributeTables::BOOLEAN: {
183     Handle(TDataStd_BooleanArray)::DownCast(anArray)->SetValue(anIndex, theValue.myBool);
184     break;
185   }
186   case ModelAPI_AttributeTables::INTEGER: {
187     Handle(TDataStd_IntegerArray)::DownCast(anArray)->SetValue(anIndex, theValue.myInt);
188     break;
189   }
190   case ModelAPI_AttributeTables::STRING: {
191     Handle(TDataStd_ExtStringArray)::DownCast(anArray)->SetValue(anIndex, theValue.myStr.c_str());
192     break;
193   }
194   }
195   owner()->data()->sendAttributeUpdated(this);
196 }
197
198 ModelAPI_AttributeTables::Value Model_AttributeTables::value(
199   const int theRow, const int theColumn, const int theTable)
200 {
201   ModelAPI_AttributeTables::Value aResult;
202   int anIndex = theTable * myRows * myCols + theRow * myCols + theColumn;
203   Handle(TDF_Attribute) anArray;
204   myLab.FindAttribute(MY_ARRAY_ID(myType), anArray);
205   switch(myType) {
206   case ModelAPI_AttributeTables::DOUBLE: {
207     aResult.myDouble = Handle(TDataStd_RealArray)::DownCast(anArray)->Value(anIndex);
208     break;
209   }
210   case ModelAPI_AttributeTables::BOOLEAN: {
211     aResult.myBool = Handle(TDataStd_BooleanArray)::DownCast(anArray)->Value(anIndex) ==
212       Standard_True;
213     break;
214   }
215   case ModelAPI_AttributeTables::INTEGER: {
216     aResult.myInt = Handle(TDataStd_IntegerArray)::DownCast(anArray)->Value(anIndex);
217     break;
218   }
219   case ModelAPI_AttributeTables::STRING: {
220     aResult.myStr = TCollection_AsciiString(Handle(TDataStd_ExtStringArray)::DownCast(anArray)->
221       Value(anIndex)).ToCString();
222     break;
223   }
224   }
225   return aResult;
226 }
227
228
229 //==================================================================================================
230 Model_AttributeTables::Model_AttributeTables(TDF_Label& theLabel)
231 {
232   myLab = theLabel;
233   reinit();
234 }
235
236 void Model_AttributeTables::reinit()
237 {
238   // check the attribute could be already presented in this doc (after load document)
239   myIsInitialized =
240     myLab.FindAttribute(TDataStd_IntegerList::GetID(), myProp) == Standard_True;
241   if (!myIsInitialized) {
242     myProp = TDataStd_IntegerList::Set(myLab);
243     myProp->Append(int(Model_AttributeTables::DOUBLE)); // default
244     myProp->Append(0);
245     myProp->Append(0);
246     myProp->Append(0);
247   }
248   TColStd_ListIteratorOfListOfInteger aListIter(myProp->List());
249   myType = ModelAPI_AttributeTables::ValueType(aListIter.Value());
250   aListIter.Next();
251   myTables = aListIter.Value();
252   aListIter.Next();
253   myRows = aListIter.Value();
254   aListIter.Next();
255   myCols = aListIter.Value();
256 }