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