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