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