Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / DDS / DDS_DicItem.cxx
1 // Copyright (C) 2005  CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA 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.
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
18 //
19 #include "DDS_DicItem.h"
20 #include "DDS_Dictionary.h"
21
22 #include <TColStd_SequenceOfInteger.hxx>
23 #include <TColStd_SequenceOfExtendedString.hxx>
24
25 #include <LDOM_Text.hxx>
26 #include <LDOMString.hxx>
27 #include <LDOM_Element.hxx>
28
29 #include <UnitsAPI.hxx>
30 #include <Units_Dimensions.hxx>
31
32 #include <TColStd_MapOfReal.hxx>
33 #include <TColStd_SequenceOfAsciiString.hxx>
34
35 IMPLEMENT_STANDARD_HANDLE(DDS_DicItem, MMgt_TShared)
36 IMPLEMENT_STANDARD_RTTIEXT(DDS_DicItem, MMgt_TShared)
37
38 DDS_DicItem::DDS_DicItem()
39 : myType( 0 ),
40 myDefValue( 0 ),
41 myMax( 0 ),
42 myMin( 0 ),
43 myMinZoom( 0.1 ),
44 myMaxZoom( 10 ),
45 myZoomOrder( 2 )
46 {
47 }
48
49 DDS_DicItem::DDS_DicItem( const DDS_DicItem& )
50 {
51 }
52
53 void DDS_DicItem::operator=( const DDS_DicItem& )
54 {
55 }
56
57 TCollection_AsciiString DDS_DicItem::GetId() const
58 {
59   return myId;
60 }
61
62 DDS_DicItem::Type DDS_DicItem::GetType() const
63 {
64   return (DDS_DicItem::Type)myType;
65 }
66
67 TCollection_ExtendedString DDS_DicItem::GetLabel() const
68 {
69   return myLabel;
70 }
71
72 TCollection_ExtendedString DDS_DicItem::GetFilter() const
73 {
74   return myFilter;
75 }
76
77 TCollection_ExtendedString DDS_DicItem::GetRequired() const
78 {
79   return myRequired;
80 }
81
82 DDS_MsgType DDS_DicItem::GetWarningLevel() const
83 {
84   return (DDS_MsgType)myWarnLevel;
85 }
86
87 TCollection_ExtendedString DDS_DicItem::GetLongDescription() const
88 {
89   return myLongDescr;
90 }
91
92 TCollection_ExtendedString DDS_DicItem::GetShortDescription() const
93 {
94   return myShortDescr;
95 }
96
97 TCollection_AsciiString DDS_DicItem::GetComponent() const
98 {
99   TCollection_AsciiString aCompName;
100   Handle(DDS_DicGroup) aComponent = Handle(DDS_DicGroup)::DownCast(myComponent);
101   if ( !aComponent.IsNull() )
102     aCompName = aComponent->GetName();
103   return aCompName;
104 }
105
106 TCollection_AsciiString DDS_DicItem::GetUnits() const
107 {
108   return GetUnits( GetActiveUnitSystem() );
109 }
110
111 TCollection_AsciiString DDS_DicItem::GetUnits( const UnitSystem& theSystem ) const
112 {
113   TCollection_AsciiString anUnits;
114   UnitData* unitData = GetUnitData( theSystem );
115   if ( unitData )
116     anUnits = unitData->myUnits;
117   return anUnits;
118 }
119
120 Standard_Real DDS_DicItem::GetMinValue() const
121 {
122   return GetMinValue( GetActiveUnitSystem() );
123 }
124
125 Standard_Real DDS_DicItem::GetMinValue( const UnitSystem& theUnitsSystem ) const
126 {
127   return FromSI( myMin, theUnitsSystem );
128 }
129
130 Standard_Real DDS_DicItem::GetMaxValue() const
131 {
132   return GetMaxValue( GetActiveUnitSystem() );
133 }
134
135 Standard_Real DDS_DicItem::GetMaxValue( const UnitSystem& theUnitsSystem ) const
136 {
137   return FromSI( myMax, theUnitsSystem );
138 }
139
140 Standard_Integer DDS_DicItem::GetPrecision() const
141 {
142   return GetPrecision( GetActiveUnitSystem() );
143 }
144
145 Standard_Integer DDS_DicItem::GetPrecision( const UnitSystem& theSystem ) const
146 {
147   Standard_Integer aRes = 0;
148   UnitData* unitData = GetUnitData( theSystem );
149   if ( unitData )
150     aRes = unitData->myPrecision;
151   return aRes;
152 }
153
154 TCollection_ExtendedString DDS_DicItem::GetDefaultValue() const
155 {
156   return GetDefaultValue( GetActiveUnitSystem() );
157 }
158
159 TCollection_ExtendedString DDS_DicItem::GetDefaultValue( const UnitSystem& theSystem ) const
160 {
161   if ( !myDefString.Length() )
162     return myDefString;
163
164   TCollection_ExtendedString aStr;
165
166   switch ( myType )
167   {
168   case Float:
169   case Integer:
170     aStr = FromSI( myDefValue, theSystem );
171     break;
172   case List:
173   case String:
174     aStr = myDefString;
175     break;
176   default:
177     break;
178   }
179   return aStr;
180 }
181
182 TCollection_AsciiString DDS_DicItem::GetFormat( const Standard_Boolean theCanonical ) const
183 {
184   return GetFormat( GetActiveUnitSystem(), theCanonical );
185 }
186
187 TCollection_AsciiString DDS_DicItem::GetFormat( const UnitSystem& theSystem,
188                                                 const Standard_Boolean theCanonical ) const
189 {
190   TCollection_AsciiString aFormat;
191   UnitData* unitData = GetUnitData( theSystem );
192   if ( unitData )
193     aFormat = unitData->myFormat;
194
195   if ( theCanonical && aFormat.Length() > 1 )
196   {
197     static TCollection_AsciiString f;
198     f = aFormat;
199     Standard_Boolean isRemoved = false;
200     while ( !isRemoved )
201     {
202       char ch = f.Value( f.Length() - 1 );
203       if ( ( ch != '%' && ch != '.' && !IsDigit( ch ) ) && f.Length() > 1 )
204         f.Remove( f.Length() - 1 );
205       else
206         isRemoved = true;
207     }
208     aFormat = f;
209   }
210
211   return aFormat;
212 }
213
214 /*!
215   Access valueList:name of the parameter. This string is void if the list is
216   not defined - then use other properties: Type, DefaultValue, MaxValue, MinValue
217 */
218 TCollection_ExtendedString DDS_DicItem::GetNameOfValues() const
219 {
220   return myListName;
221 }
222
223 /*!
224   Access valueList of the parameter. This sequence is empty if the list is
225   not defined - then use other properties: Type, DefaultValue, MaxValue, MinValue
226 */
227 Standard_Boolean DDS_DicItem::GetListOfValues( Handle(TColStd_HArray1OfExtendedString)& theStrings,
228                                                Handle(TColStd_HArray1OfInteger)& theIntegers ) const
229 {
230   theStrings  = myListRef;
231   theIntegers = myListRefID;
232   return !theIntegers.IsNull() && !theStrings.IsNull();
233 }
234
235 /*!
236   Access valueList of the parameter. This sequence is empty if the list is not
237   defined - then use other properties: Type, DefaultValue, MaxValue, MinValue
238 */
239 Standard_Boolean DDS_DicItem::GetListOfValues( Handle(TColStd_HArray1OfExtendedString)& theStrings,
240                                                Handle(TColStd_HArray1OfInteger)& theIntegers,
241                                                Handle(TColStd_HArray1OfExtendedString)& theIcons ) const
242 {
243   theStrings  = myListRef;
244   theIntegers = myListRefID;
245   theIcons    = myListRefIcons;
246   return !theIntegers.IsNull() && !theStrings.IsNull() && !theIcons.IsNull();
247 }
248
249 Standard_Boolean DDS_DicItem::GetSpecialValues( TColStd_MapOfReal& theMap ) const
250 {
251   theMap.Clear();
252   if ( !myListRef.IsNull() )
253   {
254     for ( Standard_Integer i = myListRef->Lower(); i <= myListRef->Upper(); i++ )
255     {
256       if ( myListRef->Value( i ).IsAscii() )
257       {
258         TCollection_AsciiString aStr( myListRef->Value( i ) );
259         if ( aStr.IsRealValue() )
260           theMap.Add( aStr.RealValue() );
261       }
262     }
263   }
264
265   return theMap.Extent() > 0;
266 }
267
268 /*!
269   Returns min value of lateral zooming
270 */
271 Standard_Real DDS_DicItem::GetMinZoom() const
272 {
273   return myMinZoom;
274 }
275
276 /*!
277   Returns Max Value of lateral zooming
278 */
279 Standard_Real DDS_DicItem::GetMaxZoom() const
280 {
281   return myMaxZoom;
282 }
283
284 /*!
285   Get Order of lateral zooming
286 */
287 Standard_Real DDS_DicItem::GetZoomOrder() const
288 {
289   return myZoomOrder;
290 }
291
292 Standard_Real DDS_DicItem::ToSI( const Standard_Real theVal ) const
293 {
294   return ToSI( theVal, GetActiveUnitSystem() );
295 }
296
297 Standard_Real DDS_DicItem::FromSI( const Standard_Real theVal ) const
298 {
299   return FromSI( theVal, GetActiveUnitSystem() );
300 }
301
302 /*!
303   Convert value to default SI units according to current units
304 */
305 Standard_Real DDS_DicItem::ToSI( const Standard_Real theVal, const UnitSystem& theUnitsSystem ) const
306 {
307   Standard_Real aRes = theVal;
308   UnitData* anUnitData = GetUnitData( theUnitsSystem );
309   if ( anUnitData )
310     aRes = anUnitData->myZero + aRes * anUnitData->myScale;
311   return aRes;
312 }
313
314 /*!
315   Convert value from default SI units according to current units
316 */
317 Standard_Real DDS_DicItem::FromSI( const Standard_Real theVal, const UnitSystem& theUnitsSystem ) const
318 {
319   Standard_Real aRes = theVal;
320   UnitData* anUnitData = GetUnitData( theUnitsSystem );
321   if ( anUnitData )
322     aRes = ( aRes - anUnitData->myZero ) / anUnitData->myScale;
323   return aRes;
324 }
325
326 /*!
327   Returns 'true' if specified data exist.
328 */
329 Standard_Boolean DDS_DicItem::HasData( const Standard_Integer flag ) const
330 {
331   return ( myData & flag ) == flag;
332 }
333
334 /*!
335   Parse record in XML file and retrieve information relevant for this data dic item
336 */
337 void DDS_DicItem::FillDataMap( TCollection_AsciiString theID, const LDOM_Element& theDatum,
338                                const LDOM_Element& theCompElement, const LDOM_Element& theDocElement,
339                                const TColStd_SequenceOfAsciiString& theSystems )
340 {
341   TCollection_AsciiString aLabel    = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_LABEL" ) );
342   TCollection_AsciiString aFormat   = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_FORMAT" ) );
343   TCollection_AsciiString aFilter   = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_FILTER" ) );
344   TCollection_AsciiString aRequired = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_REQUIRED" ) );
345
346   TCollection_AsciiString aBaseKeyWord = DDS_Dictionary::KeyWord( "DATUM_UNITS" );
347
348   for ( Standard_Integer j = 1; j <= theSystems.Length(); j++ )
349   {
350     UnitSystem anUnitSystem = theSystems.Value( j );
351     if ( !anUnitSystem.Length() )
352       continue;
353
354     TCollection_AsciiString aUnitKeyword = anUnitSystem + aBaseKeyWord;
355
356     if ( !myUnitData.IsBound( anUnitSystem ) )
357       myUnitData.Bind( anUnitSystem, UnitData() );
358
359     UnitData& anUnitData = myUnitData.ChangeFind( anUnitSystem );
360     anUnitData.myUnits = theDatum.getAttribute( LDOMString( aUnitKeyword.ToCString() ) );
361   }
362
363   if ( theSystems.Length() && myUnitData.IsBound( theSystems.First() ) &&
364        !myUnitData.Find( theSystems.First() ).myUnits.Length() )
365   {
366     TCollection_AsciiString units = theDatum.getAttribute( LDOMString( aBaseKeyWord.ToCString() ) );
367     if ( units.Length() )
368       myUnitData.ChangeFind( theSystems.First() ).myUnits = units;
369   }
370
371   TCollection_AsciiString units;
372   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator iter( myUnitData ); iter.More() && units.IsEmpty(); iter.Next() )
373     units = iter.Value().myUnits;
374
375   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator itr( myUnitData ); itr.More(); itr.Next() )
376   {
377     UnitData& dataUnits = itr.ChangeValue();
378     if ( dataUnits.myUnits.IsEmpty() )
379       dataUnits.myUnits = units;
380   }
381   
382   // 2. Elements ( domain, description )
383   Standard_Real aRealMinV = 0;
384   Standard_Real aRealMaxV = 0;
385   Standard_Real aRealDefV = 0;
386
387   TCollection_AsciiString aType;
388
389   DDS_MsgType aWrongValue = DDS_MT_NONE;
390   DDS_DicItem::Type aEnumType = DDS_DicItem::Unknown;
391
392   TCollection_AsciiString aMinV;
393   TCollection_AsciiString aMaxV;
394   TCollection_AsciiString aDefV;
395   TCollection_AsciiString aListName;
396
397   TCollection_AsciiString aLongD;
398   TCollection_AsciiString aShortD;
399
400   TColStd_SequenceOfInteger aSeqOfValueID;
401   TColStd_SequenceOfExtendedString aSeqOfValue;
402   TColStd_SequenceOfExtendedString aSeqOfValueIconName;
403
404   // Presentation
405   Standard_Real aMinZoom   = 0;
406   Standard_Real aMaxZoom   = 0;
407   Standard_Real aZoomOrder = 0;
408
409   // Datum::Reports tags (if any)
410   LDOM_Element aWLev = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "WARNING_LEVEL" ) );
411   if ( !aWLev.isNull() )
412   {
413     TCollection_AsciiString aWrongValWL = aWLev.getAttribute( DDS_Dictionary::KeyWord( "WRONG_VALUE" ) );
414     if ( aWrongValWL.IsEqual( "Info" ) )
415       aWrongValue = DDS_MT_INFO;
416     else if ( aWrongValWL.IsEqual( "Warning" ) )
417       aWrongValue = DDS_MT_WARNING;
418     else if ( aWrongValWL.IsEqual( "Alarm" ) )
419       aWrongValue = DDS_MT_ALARM;
420     else if ( aWrongValWL.IsEqual( "Error" ) )
421       aWrongValue = DDS_MT_ERROR;
422   }
423
424   // Datum::Presentation
425   LDOM_Element aPrs = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "PRS" ) );
426   if ( !aPrs.isNull() )
427   {
428     LDOM_Element aLateralZoom = aPrs.GetChildByTagName( DDS_Dictionary::KeyWord( "LATERAL_ZOOM" ) );
429     if ( !aLateralZoom.isNull() )
430     {
431       TCollection_AsciiString aMinZoomStr   = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_MINV" ) );
432       TCollection_AsciiString aMaxZoomStr   = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_MAXV" ) );
433       TCollection_AsciiString aZoomOrderStr = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_ORDER" ) );
434       
435       aMinZoomStr.RemoveAll( ' ' );
436       if ( aMinZoomStr.IsRealValue() )
437         aMinZoom = aMinZoomStr.RealValue();
438
439       aMaxZoomStr.RemoveAll( ' ' );
440       if ( aMaxZoomStr.IsRealValue() )
441         aMaxZoom = aMaxZoomStr.RealValue();
442
443       aZoomOrderStr.RemoveAll( ' ' );
444       if ( aZoomOrderStr.IsRealValue() )
445         aZoomOrder = aZoomOrderStr.RealValue();
446     }
447   }
448
449   // Quantity::Domain record as the only child of that tag name
450   LDOM_Element aDomain = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "DY_DOMAIN" ) );
451   if ( !aDomain.isNull() )
452   {
453     LDOM_Element aValueDescr = aDomain.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_DESCR" ) );
454     if ( !aValueDescr.isNull() )
455     {
456       // read: valueDescr? (type?,min?,max?,default?)
457       aType = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_TYPE" ) );
458       if ( aType.IsEqual( "String" ) )
459         aEnumType = String;
460       else if ( aType.IsEqual( "Float" ) )
461         aEnumType = Float;
462       else if ( aType.IsEqual( "Integer" ) )
463         aEnumType = Integer;
464
465       if ( !aValueDescr.getAttributeNode( DDS_Dictionary::KeyWord( "VD_MINV" ) ).isNull() )
466         myData |= MinValue;
467       aMinV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_MINV" ) );
468       aMinV.RemoveAll( ' ' );
469       if ( aMinV.IsRealValue() )
470         aRealMinV = aMinV.RealValue();
471       if ( !aValueDescr.getAttributeNode( DDS_Dictionary::KeyWord( "VD_MAXV" ) ).isNull() )
472         myData |= MaxValue;
473       aMaxV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_MAXV" ) );
474       aMaxV.RemoveAll( ' ' );
475       if ( aMaxV.IsRealValue() )
476         aRealMaxV = aMaxV.RealValue();
477       aDefV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_DEFV" ) );
478       if ( !aValueDescr.getAttributeNode( DDS_Dictionary::KeyWord( "VD_DEFV" ) ).isNull() )
479         myData |= DefaultValue;
480
481       aDefV.RemoveAll( ' ' );
482       if ( aDefV.IsRealValue() )
483         aRealDefV = aDefV.RealValue();
484
485       TCollection_AsciiString aSpecVal = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_SPEC" ) );
486       Split( aSpecVal, myListRef );
487     }
488     else
489     {
490       //  read: listRef? (list?)
491       LDOM_Element aListRef = aDomain.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST_REF" ) );
492       if ( !aListRef.isNull() )
493       {
494         aType = "List";
495         aEnumType = List;                       
496         LDOMString aListId = aListRef.getAttribute( DDS_Dictionary::KeyWord( "VLR_LIST" ) );
497         aDefV = aListRef.getAttribute( DDS_Dictionary::KeyWord( "VD_DEFV" ) );
498         aDefV.RemoveAll( ' ' );
499         LDOM_Element foundListItem;
500         for ( LDOM_Element aListItem = theCompElement.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST" ) );
501               aListItem != NULL && foundListItem == NULL; aListItem = aListItem.GetSiblingByTagName() )
502         {
503           if ( aListItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_ID" ) ).equals( aListId ) )
504             foundListItem = aListItem;
505
506         }
507         for ( LDOM_Element aLstItem = theDocElement.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST" ) );
508               aLstItem != NULL && foundListItem == NULL; aLstItem = aLstItem.GetSiblingByTagName() )
509         {
510           if ( aLstItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_ID" ) ).equals( aListId ) )
511             foundListItem = aLstItem;
512         }
513
514         if ( foundListItem != NULL )
515         {
516           //  The appropriate list of values is found: store the list name
517           aListName = foundListItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_NAME" ) );
518           //  Iteration through the list of values
519           LDOM_Element aListItemValue = foundListItem.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUE" ) );
520           while ( aListItemValue != NULL )
521           {
522             // read value ID
523             TCollection_AsciiString aListValueID = aListItemValue.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUEID" ) );
524             if ( aListValueID.IsIntegerValue() )
525             {
526               //  Read the text in the element "value"
527               //LDOM_Text aListItemTxt = (const LDOM_Text&)aListItemValue.getFirstChild();
528               LDOM_Node aNode = aListItemValue.getFirstChild();
529               const LDOM_Text& aText = (const LDOM_Text&) aNode;
530               LDOM_Text aListItemTxt(aText);
531               if ( !aListItemTxt.isNull() )
532               {
533                 // adding ID and text value to sequence
534                 aSeqOfValueID.Append( aListValueID.IntegerValue() );
535                 aSeqOfValue.Append( aListItemTxt.getData() );
536                 // adding icon file name (optional) to sequence
537                 TCollection_ExtendedString aListValueIcon = aListItemValue.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUEICON" ) );
538                 aSeqOfValueIconName.Append( aListValueIcon );
539               }
540               aListItemValue = aListItemValue.GetSiblingByTagName();
541             }
542           }
543         }
544       }
545     }
546   }
547
548   // Quantity::Description record as the only child of that tag name
549   LDOM_Element aDescr = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "DESCR" ) );
550   if ( !aDescr.isNull() )
551   {
552     // short description (#PCDATA)*
553     LDOM_Element aShDescr = aDescr.GetChildByTagName( DDS_Dictionary::KeyWord( "SHORT_D" ) );
554     if ( !aShDescr.isNull() )
555     {
556       // text is always a sub-node of element, containing it
557       //LDOM_Text aShDescrTxt = (const LDOM_Text&)aShDescr.getFirstChild();
558       LDOM_Node aNode = aShDescr.getFirstChild();
559       const LDOM_Text& aText = (const LDOM_Text&) aNode;
560       LDOM_Text aShDescrTxt(aText);
561       if ( !aShDescrTxt.isNull() )
562         aShortD = aShDescrTxt.getData();
563     }
564
565     // long description (#PCDATA)*
566     LDOM_Element aLDescr = aDescr.GetChildByTagName( DDS_Dictionary::KeyWord( "LONG_D" ) );
567     if ( !aLDescr.isNull() )
568     {
569       // text is always a sub-node of element, containing it
570       //LDOM_Text aLDescrTxt = (const LDOM_Text&)aLDescr.getFirstChild();
571       LDOM_Node aNode = aLDescr.getFirstChild();
572       const LDOM_Text& aText = (const LDOM_Text&) aNode;
573       LDOM_Text aLDescrTxt(aText);
574       if ( !aLDescrTxt.isNull() )
575         aLongD = aLDescrTxt.getData();
576     }
577   }
578
579   NCollection_DataMap<UnitSystem, Handle(Units_Dimensions)> aDimMap;
580
581   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator it( myUnitData ); it.More(); it.Next() )
582   {
583     UnitData& anUnitData = it.ChangeValue();
584
585     // check units
586     anUnitData.myZero  = 0.;
587     anUnitData.myScale = 1.;
588     try {
589       Standard_CString aUnitDataStr;
590       aUnitDataStr = (Standard_CString)anUnitData.myUnits.ToCString();
591       if ( anUnitData.myUnits.ToCString()[0] && strcmp( anUnitData.myUnits.ToCString(), "%" ) )
592       {
593         Handle(Units_Dimensions) aDim;
594         anUnitData.myZero  = UnitsAPI::AnyToSI( 0.0, aUnitDataStr, aDim );
595         anUnitData.myScale = UnitsAPI::AnyToSI( 1.0, aUnitDataStr, aDim ) - anUnitData.myZero;
596         UnitsAPI::AnyFromSI( 1.0, aUnitDataStr );
597         if ( !aDimMap.IsBound( it.Key() ) )
598           aDimMap.Bind( it.Key(), aDim );
599       }
600       else if ( anUnitData.myUnits.ToCString()[0] ) // treat '%' as unit with scale 100
601         anUnitData.myScale = 0.01;
602     }
603           catch( Standard_Failure ) {
604       anUnitData.myUnits.Clear();
605     }
606
607     Handle(Units_Dimensions) aPrev;
608     Standard_Boolean aStatus = Standard_True;
609     for ( NCollection_DataMap<UnitSystem, Handle(Units_Dimensions)>::Iterator itr( aDimMap );
610           itr.More() && aStatus; itr.Next() )
611     {
612       if ( itr.Value().IsNull() )
613         continue;
614
615       if ( aPrev.IsNull() )
616         aPrev = itr.Value();
617
618       aStatus = aPrev->IsEqual( itr.Value() );
619     }
620
621     if ( !aStatus )
622       printf( "Error in DataDictionary: Different dimensions for %s item", theID.ToCString() );
623   }
624
625   myId                = theID;
626   myType              = aEnumType;
627   myWarnLevel         = aWrongValue;
628   myLabel             = aLabel.ToCString();
629   myFilter            = aFilter.ToCString();
630   myLongDescr         = aLongD.ToCString();
631   myShortDescr        = aShortD.ToCString();
632   myMin               = aRealMinV;
633   myMax               = aRealMaxV;
634   myDefValue          = aRealDefV;
635   myDefString         = aDefV.ToCString();
636   myRequired          = aRequired.ToCString();
637   myListName          = aListName.ToCString();
638   myMinZoom           = aMinZoom;
639   myMaxZoom           = aMaxZoom;
640   myZoomOrder         = aZoomOrder;
641
642   // prepare formats
643   PrepareFormats( aFormat );
644
645   const Standard_Integer aLength = aSeqOfValue.Length();
646   if ( aLength > 0 )
647   {
648     myListRef      = new TColStd_HArray1OfExtendedString( 1, aLength );
649     myListRefID    = new TColStd_HArray1OfInteger( 1, aLength );
650     myListRefIcons = new TColStd_HArray1OfExtendedString( 1, aLength );
651     for ( Standard_Integer i = aLength; i > 0; i-- )
652     {
653       myListRef->ChangeValue( i ) = aSeqOfValue.Value( i );
654       myListRefID->ChangeValue( i ) = aSeqOfValueID.Value( i );
655       myListRefIcons->ChangeValue( i ) = aSeqOfValueIconName.Value( i );
656     }
657   }
658
659   if ( myType == List && myDefString == "" && !myListRef.IsNull() && myListRef->Length() > 0 )
660     myDefString = myListRef->Value( myListRef->Lower() );
661 }
662
663 /*!
664   Returns default formats for each unit systems
665 */
666 void DDS_DicItem::GetDefaultFormat()
667 {
668   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator it( myUnitData ); it.More(); it.Next() )
669   {
670     UnitData& anUnitData = it.ChangeValue();
671
672     switch ( myType )
673     {
674     case Integer:
675       anUnitData.myFormat = "%d";
676       break;
677     case Float:
678       anUnitData.myFormat = "%g";
679       break;
680     case String:
681     default:
682       anUnitData.myFormat.Clear();
683       break;;
684     }
685   }
686 }
687
688 /*!
689   Returns format for the string
690 */
691 void DDS_DicItem::GetStringFormat( const TCollection_AsciiString& theFlags,
692                                    const TCollection_AsciiString& theWidth,
693                                    const TCollection_AsciiString& thePrecision,
694                                    const TCollection_AsciiString& theTypePrefix,
695                                    TCollection_AsciiString& theFormat )
696 {
697   theFormat = "%";
698   theFormat += theFlags;
699   theFormat += theWidth;
700
701   if ( !thePrecision.IsEmpty() ) 
702   {
703     theFormat += ".";
704     theFormat += thePrecision;
705   }
706
707   theFormat += theTypePrefix;
708   theFormat += "s";
709 }
710
711 /*!
712   Returns format for the integer
713 */
714 void DDS_DicItem::GetIntegerFormat( const TCollection_AsciiString& theFlags,
715                                     const TCollection_AsciiString& theWidth,
716                                     const TCollection_AsciiString& thePrecision,
717                                     const TCollection_AsciiString& theTypePrefix,
718                                     const Standard_Character theType,
719                                     TCollection_AsciiString& theFormat )
720 {
721   Standard_Integer aPrecision = 0;
722   if ( !thePrecision.IsEmpty() )
723     aPrecision = thePrecision.IntegerValue();
724   Standard_Integer aWidth = 0;
725
726   if ( !theWidth.IsEmpty() )
727     aWidth = theWidth.IntegerValue();
728
729   if ( !thePrecision.IsEmpty() && aPrecision < 0 )
730   {
731     // possible value 0.1 will be 10.0
732     aWidth -= aPrecision;
733     aPrecision = 0;
734   }
735
736   if ( !thePrecision.IsEmpty() && aPrecision > ( aWidth - 2 ) )
737     aWidth = aPrecision + 2;
738
739   theFormat = "%";
740
741   theFormat += theFlags;
742   if ( !theWidth.IsEmpty() )
743     theFormat += aWidth;
744
745   theFormat += theTypePrefix;
746   theFormat += theType;
747 }
748
749 /*!
750   Returns format for the float
751 */
752 void DDS_DicItem::GetFloatFormat( const TCollection_AsciiString& theFlags,
753                                   const TCollection_AsciiString& theWidth,
754                                   const TCollection_AsciiString& thePrecision,
755                                   const TCollection_AsciiString& theTypePrefix,
756                                   const Standard_Character theType,
757                                   TCollection_AsciiString& theFormat )
758 {
759   Standard_Integer aPrecision = 0;
760   if ( !thePrecision.IsEmpty() )
761     aPrecision = thePrecision.IntegerValue();
762   Standard_Integer aWidth = 0;
763
764   if (!theWidth.IsEmpty() )
765     aWidth = theWidth.IntegerValue();
766
767   if (!thePrecision.IsEmpty() && aPrecision < 0 )
768   {
769     // possible value 0.1 will be 10.0
770     aWidth -= aPrecision;
771     aPrecision = 0;
772   }
773
774   if ( !thePrecision.IsEmpty() && aPrecision > ( aWidth - 2 ) )
775   {
776     aWidth = aPrecision + 2;
777   }
778
779   theFormat = "%";
780   theFormat += theFlags;
781
782   if ( !theWidth.IsEmpty() ) 
783     theFormat += aWidth;
784
785   if ( !thePrecision.IsEmpty() ) 
786   {
787     theFormat += ".";
788     theFormat += aPrecision;
789   }
790
791   theFormat += theTypePrefix;
792   theFormat += theType;
793 }
794
795 /*!
796   Prepares three formants for each unit systems
797 */
798 void DDS_DicItem::PrepareFormats( const TCollection_AsciiString&  theFormat )
799 {
800   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator it( myUnitData ); it.More(); it.Next() )
801   {
802     UnitData& anUnitData = it.ChangeValue();
803
804     anUnitData.myFormat = theFormat;
805     anUnitData.myPrecision = 0;
806   }
807
808   TCollection_AsciiString aPrecisionStr;
809   if ( theFormat.IsEmpty() && myType == List )
810     return;
811
812   // checking % presenting
813   if ( *theFormat.ToCString() != '%' )
814   {
815     GetDefaultFormat();
816     return;
817   }
818
819   TCollection_AsciiString aStr = ( theFormat.ToCString() + 1 );
820   Standard_Character aType = aStr.Value( aStr.Length() );
821
822   if ( ( aType != 's' && myType == String ) ||
823        ( aType != 'd' && myType == Integer ) ||
824        ( aType != 'f' && aType != 'g' && aType != 'e' && aType != 'G' && aType != 'E' && myType == Float ) )
825   {
826     GetDefaultFormat();
827     return;
828   }
829
830   // removing type character
831   aStr.Trunc( aStr.Length() - 1 );
832
833   TCollection_AsciiString aFlags;
834   while ( !aStr.IsEmpty() && aStr.Value( 1 ) != '.' && ( aStr.Value( 1 ) < '0' || aStr.Value( 1 ) > '9' ) )
835   {
836     aFlags = aFlags + aStr.Value( 1 );
837     aStr.Remove( 1 );
838   }
839
840   Standard_Integer aPos = 1;
841   while ( aPos <= aStr.Length() && ( aStr.Value( aPos ) == '.' ||
842           ( aStr.Value( aPos ) >= '0' && aStr.Value( aPos ) <= '9' ) ) )
843     aPos++;
844
845   TCollection_AsciiString aTypePrefix;
846   if ( aPos <= aStr.Length() )
847   {
848     aTypePrefix = aStr.SubString( aPos, aStr.Length() );
849     aStr.Trunc( aPos - 1 );
850   }
851
852   Standard_Integer aBasePrecision = 0;
853
854   // taking width and precision
855   TCollection_AsciiString aPrecision;
856
857   aPos = aStr.Search( "." );
858   if ( aPos >= 0 ) 
859   {
860     // aPrecision is defined
861     aPrecision = aStr.Split( aPos );
862     aStr.Remove( aStr.Length() );
863     if ( !aPrecision.IsEmpty() )
864     {
865       if ( !aPrecision.IsIntegerValue() ) 
866       { 
867         GetDefaultFormat();
868         return;
869       }
870       else
871       {
872         aPrecisionStr  = aPrecision;
873         aBasePrecision = aPrecision.IntegerValue();
874       }
875     }
876   }
877
878   if ( !aStr.IsEmpty() && !aStr.IsIntegerValue() )
879   {
880     GetDefaultFormat();
881     return;
882   }
883
884   NCollection_DataMap<UnitSystem, UnitData>::Iterator itr;
885
886   switch ( myType )
887   {
888   case String:
889     for ( itr.Initialize( myUnitData ); itr.More(); itr.Next() )
890     {
891       if ( aType != 'f' && aType != 'g' && aType != 'e' && aType != 'G' && aType != 'E' )
892         GetStringFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, itr.ChangeValue().myFormat );
893     }
894     break;
895   case Float:
896   case Integer:
897     for ( itr.Initialize( myUnitData ); itr.More(); itr.Next() )
898     {
899       UnitData& anUnitData = itr.ChangeValue();
900       Standard_Integer aAmendment =
901         (Standard_Integer)log10( 10.0 / DDS_Dictionary::FromSI( 10.0, anUnitData.myUnits.ToCString() ) );
902       anUnitData.myPrecision = aBasePrecision + aAmendment;
903       aPrecisionStr = TCollection_AsciiString( anUnitData.myPrecision );
904
905       // create a formats
906       if ( myType == Integer )
907         GetIntegerFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, aType, anUnitData.myFormat );
908       else
909         GetFloatFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, aType, anUnitData.myFormat );
910     }
911     break;
912   default:;
913     GetDefaultFormat();
914     break;
915   }
916 }
917
918 void DDS_DicItem::Split( const TCollection_AsciiString& theStr, Handle(TColStd_HArray1OfExtendedString)& aRes )
919 {
920   aRes.Nullify();
921
922   if ( theStr.Length() > 0 )
923   {
924     TCollection_AsciiString aStr = theStr;
925     TColStd_SequenceOfAsciiString aSeq;
926     Standard_Integer anIndex = aStr.SearchFromEnd( (Standard_CString)" " );
927     while( anIndex > 1 )
928     {
929       TCollection_AsciiString tmpStr = aStr.Split( anIndex - 1 );
930       tmpStr.RemoveAll( ( Standard_Character )' ' );
931       if ( tmpStr.Length() > 0 )
932         aSeq.Append( tmpStr );
933       anIndex = aStr.SearchFromEnd( (Standard_CString)" " );
934     }
935
936     aStr.RemoveAll( ( Standard_Character )' ' );
937     if ( aStr.Length() > 0 )
938       aSeq.Append( aStr );
939
940     if ( aSeq.Length() > 0 )
941     {
942       aRes = new TColStd_HArray1OfExtendedString( 1, aSeq.Length() );
943       for ( int i = 1, n = aSeq.Length(); i <= n; i++ )
944         aRes->ChangeValue( i ) = aSeq( i );
945     }
946   }
947 }
948
949 DDS_DicItem::UnitData* DDS_DicItem::GetUnitData( const UnitSystem& sys ) const
950 {
951   UnitData* unit = 0;
952
953   if ( myUnitData.IsBound( sys ) )
954     unit = (UnitData*)&myUnitData.Find( sys );
955
956   return unit;
957 }
958
959 DDS_DicItem::UnitSystem DDS_DicItem::GetActiveUnitSystem() const
960 {
961   UnitSystem aSystem;
962   Handle(DDS_DicGroup) aComponent = Handle(DDS_DicGroup)::DownCast(myComponent);
963   if ( !aComponent.IsNull() )
964     aSystem = aComponent->GetActiveUnitSystem();
965   return aSystem;
966 }